.title TCP/UDP Ethernet Driver ; This driver requires the EQ/EU device driver ; which supports internal frame queueing. ; ; This I/O driver supports the TCP/UDP ; task. This driver uses four EN units: ; ; 0 - recv protocol = EARP ; 1 - recv protocol = ERARP ; 2 - recv protocol = EIP ; 3 - xmit (protocol not used when xmitting) ; ; DECUS C Calling Format ; ; jsr r5,csv$ ;save r2,r3, and r4 ; ;r5 is parameter base ; ;c$pmtr(r5) is first argument ; ;c$pmtr+2(r5) is second argument ; ;... ; ;return args in r0 ; ... ; user code ; ... ; ; jmp cret$ ;restore r2-r5 and return ; .mcall .lookup .close .spfun .abtio .mcall .exit .rsum .print .cstat MINPKT = 32. ;minimum output packet size MAXPKT = 759. ;maximum output packet size TCPPKT = 738. ;buffer length required for a ;1408 byte CREDIT TCP packet ARPPKT = 290. ;buffer length required ;for an arp packet RARPKT = 290. ;buffer length required ;for a rarp packet YES = 0 ;DEBUG state NO = 1 DEBUG = YES ;debug mode enabled ERRBYT = 52 ;IO error byte EARP = 003010 ;0x0608 ;protocols ERARP = 132600 ;0x3580 EIP = 000010 ;0x0008 SEARP = 004006 ;0x0806 ;swapped prpotocols SERARP = 100065 ;0x8035 SEIP = 004000 ;0x0800 enchan = 0 ;offsets endev = 2 enprot = 4 enpkts = 6 enbufr = 10 enflgs = 12 en.alc = 000001 en.prt = 000002 en.rcv = 000004 en.que = 000010 ENTLEN = 14 ;table length .page .sbttl Configuration Data .psect c$data en0: .rad50 /EN0EN0EN0EN0/ ;filespecs en1: .rad50 /EN1EN1EN1EN1/ en2: .rad50 /EN2EN2EN2EN2/ en3: .rad50 /EN3EN3EN3EN3/ setup: .word 10, en0, EIP, TCPPKT, buff1, en.alc!en.prt!en.rcv .word 11, en1, EARP, ARPPKT, buff2, en.alc!en.prt!en.rcv .word 12, en2, ERARP, RARPKT, buff3, en.alc!en.prt!en.rcv setupx: .word 13, en3, 0, 0, 0, en.alc!en.que .word 0 tmpchn =: 14 ;temporary channel tmpenu =: en0 ;temporary unit ethsts: .word 0,0 ;protocol initialization ethadd: .word 0,0,0 ;ethernet address argmnt: .blkw 6 ;argument block chstat: .blkw 6 ;channel status pktlst: .blkw 4. ;packet list chnmsk = ^C3 pktmsk = ^C7 pkiptr: .word 0 ;received packet pointer pkrptr: .word 0 ;retrieved packet pointer bufupd: .word 0 ;update packet buff1: .blkw TCPPKT ;buffer 1 for IP's buff2: .blkw ARPPKT ;buffer 2 for ARP's buff3: .blkw RARPKT ;buffer 3 for RARP's .psect c$code .page .sbttl Get Ethernet Address ; ; engetaddr(s); char *s ; engetaddr:: jsr r5,csv$ .if ne DEBUG clr errcnt .endc mov #ethadd,r0 ;check for the ethernet address mov (r0)+,r1 bis (r0)+,r1 bis (r0),r1 bne 3$ ;have one ! ; Lookup the device and assign a channel .lookup #argmnt,#tmpchn,#tmpenu bcc 1$ .if eq DEBUG mov #emsg1,r0 jsr pc,error .iff inc errcnt .endc ; Get Physical Address 1$: .spfun #argmnt,#tmpchn,#207,#ethadd-2,#0,#0 bcc 2$ .if eq DEBUG mov #emsg8,r0 jsr pc,error .iff inc errcnt .endc ; Close the channel 2$: .close #tmpchn 3$: mov #ethadd,r0 ;return the ethernet address mov c$pmtr(r5),r1 mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0),(r1) .if eq DEBUG jmp cret$ .iff jmp enexit .endc .page .sbttl Get Handler Statistics ; ; engetstats(*s, n) *s an array of n elements ; engetstats:: jsr r5,csv$ .if ne DEBUG clr errcnt .endc ; Lookup the device and assign a channel .lookup #argmnt,#tmpchn,#tmpenu bcc 1$ .if eq DEBUG mov #emsg1,r0 jsr pc,error .iff inc errcnt .endc ; Get Handler Statistics 1$: .spfun #argmnt,#tmpchn,#210,c$pmtr(r5),c$pmtr+2(r5),#0 bcc 2$ .if eq DEBUG mov #emsg9,r0 jsr pc,error .iff inc errcnt .endc ; Close the channel 2$: .close #tmpchn .if eq DEBUG jmp cret$ .iff jmp enexit .endc .page .sbttl Open all EN channels ; ; enopen(); ; enopen:: jsr r5,csv$ .if ne DEBUG clr errcnt .endc mov #setup,r2 ;set up table ; Lookup the device and assign a channel 1$: .lookup #argmnt,enchan(r2),endev(r2) bcc 2$ .if eq DEBUG mov #emsg1,r0 jsr pc,error .iff inc errcnt .endc ; Allocate the device 2$: bit #en.alc,enflgs(2) beq 3$ .spfun #argmnt,enchan(r2),#200,#ethadd-2,#0,#1 bcc 3$ .if eq DEBUG mov #emsg2,r0 jsr pc,error .iff inc errcnt .endc ; Set up the receiver protocols 3$: bit #en.prt,enflgs(r2) beq 4$ clr ethsts mov enprot(r2),ethsts+2 ;load protocol .spfun #argmnt,enchan(r2),#202,#ethsts,#0,#1 bcc 4$ .if eq DEBUG mov #emsg4,r0 jsr pc,error .iff inc errcnt .endc ; Start up the designated receivers 4$: bit #en.rcv,enflgs(r2) beq 5$ .spfun #argmnt,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn bcc 5$ .if eq DEBUG mov #emsg6,r0 jsr pc,error .iff inc errcnt .endc ; Enable Frame queueing 5$: bit #en.que,enflgs(r2) beq 6$ .spfun #argmnt,enchan(r2),#206,enbufr(r2),#0,#1 bcc 6$ .if eq DEBUG mov #emsg7,r0 jsr pc,error .iff inc errcnt .endc 6$: add #ENTLEN,r2 tst (r2) beq 7$ jmp 1$ 7$: mov errcnt,r0 ;exit status .if eq DEBUG jmp cret$ .iff jmp enexit .endc .page .sbttl Close all EN channels ; ; enclose(); ; enclose:: jsr r5,csv$ mov #setup,r2 ;set up table ; Abort all pending i/o 1$: .abtio enchan(r2) ; Close the channel .close enchan(r2) add #ENTLEN,r2 tst (r2) bne 1$ jmp cret$ .page .sbttl Receive Ethernet Packets ; ; packet_buffer = enrecv(); ; enrecv:: jsr r5,csv$ cmp pkrptr,pkiptr ; any packets ? bne 1$ clr bufupd ; no packets clr r0 jmp cret$ 1$: mov pkrptr,r2 mov pktlst(r2),r1 ; extract packet pointer add #2,r2 bic #pktmsk,r2 mov r2,pkrptr mov r1,bufupd ; save for enupdate mov enbufr(r1),r0 jmp cret$ .page .sbttl Transmit Ethernet Packets ; ; int enxmit((char *)ptr, size) ; ; ; The packet presented to enxmit() is ; expected to have 2 words prefixed to ; the actual data packet. ; ; DLAYER contains the 2 word prefix. ; enxmit:: jsr r5,csv$ .if ne DEBUG clr errcnt .endc mov c$pmtr(r5),r3 ;packet buffer address mov #-1,(r3) ;preset status flag to error mov #setupx,r2 ;unit select mov r3,enbufr(r2) ;save for error reports mov c$pmtr+2(r5),r1 ;byte count inc r1 ;round bytes to words asr r1 cmp #MINPKT,r1 ;bound the packet blos 1$ ;from MINPKT to MAXPKT mov #MINPKT,r1 ;words br 2$ 1$: cmp #MAXPKT,r1 blo 3$ ;packet length error 2$: mov r1,2(r3) ;set packet length .spfun #argmnt,enchan(r2),#204,r3,r1,#0 bcc 3$ .if eq DEBUG mov #emsg5,r0 jsr pc,error .iff inc errcnt .endc 3$: mov (r3),r0 ;return i/o status .if eq DEBUG jmp cret$ .iff jmp enexit .endc .page .sbttl Update Buffer Usage ; ; enupdate() ; enupdate:: jsr r5,csv$ .if ne DEBUG clr errcnt .endc mov bufupd,r2 ;a buffer used ? beq 1$ ;no - skip clr bufupd ;reclaim buffer .spfun #argmnt,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn bcc 1$ .if eq DEBUG mov #emsg6,r0 jsr pc,error .iff inc errcnt .endc 1$: .if eq DEBUG jmp cret$ .iff jmp enexit .endc .page .sbttl Receive Completion Routine cmpltn: bic #chnmsk,r1 ; compute packet pointer mul #ENTLEN,r1 ; from channel number add #setup,r1 mov pkiptr,r2 mov r1,pktlst(r2) ; put entry into packet list add #2,r2 bic #pktmsk,r2 mov r2,pkiptr .rsum ; resume any suspension rts pc .if ne DEBUG enexit: tst errcnt ;any errors beq 1$ mov r0,-(sp) .print #iomsg .print #emsg0 mov (sp)+,r0 1$: jmp cret$ ;return .endc .if eq DEBUG error: inc errcnt ;update error counter mov r0,-(sp) .print #iomsg .print (sp)+ ;print specified error, .print #iomsg mov enchan(r2),r0 ;channel, jsr r5,twodgt chnerr movb @#ERRBYT,r0 ;ERRBYT, jsr r5,twodgt ioerr mov enbufr(r2),r0 ;and EN status mov (r0),r0 jsr r5,twodgt stserr .print #errmsg rts pc twodgt: mov r1,-(sp) ;two octal digit converter mov (r5)+,r1 mov r0,-(sp) ash #-3,r0 bic #^C7,r0 add #'0,r0 movb r0,(r1)+ mov (sp)+,r0 bic #^C7,r0 add #'0,r0 movb r0,(r1) mov (sp)+,r1 rts r5 .endc .psect c$data errcnt: .word 0 ;error counter .psect c$strn iomsg: .ascii /ENDRVR-/<200> .if ne DEBUG emsg0: .asciz /F-Initialization Failure/ .iff emsg1: .asciz /F-.lookup failure/ emsg2: .asciz /F-.spfun 200, unable to allocate device/ emsg3: .asciz /F-.spfun 200, unable to deallocate device/ emsg4: .asciz /F-.spfun 202, unable to initialize protocol/ emsg5: .asciz /F-.spfun 204, xmtr failure/ emsg6: .asciz /F-.spfun 205, unable to start receiver/ emsg7: .asciz /F-.spfun 206, unable to enable frame queueing/ emsg8: .asciz /F-.spfun 207, unable to get physical address/ emsg9: .asciz /F-.spfun 210, unable to get handler statistics/ errmsg: .ascii /I-CHANNEL = / chnerr: .ascii /00, / .ascii /ERRBYT = / ioerr: .ascii /00, / .ascii /STATUS = / stserr: .asciz /00/ .endc .even .end