.title TCP/UDP Ethernet Driver ; This driver may use 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 = EIP ; 1 - recv protocol = EARP ; 2 - recv protocol = ERARP ; 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 ; rts pc ;does the same (cret$ follows csv$) ; .include "os.mac" .mcall .lookup .close .spfun .abtio .mcall .exit .print .cstat MINPKT = 32. ;minimum output packet size MAXPKT = 759. ;maximum output packet size TCPPKT = 759. ;buffer length required for a ;1460 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 = NO ;debug mode disabled 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/ .if ne sp$207 ;.spfun 207 required tmpenu =: en0 ;temporary unit .iff en7: .rad50 /EN7EN7EN7EN7/ ;temporary tmpenu =: en7 ;temporary unit .endc tmpchn =: 14 ;temporary channel 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 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 4$ ;have one ! ; Lookup the device and assign a channel ; .lookup #lkpdev,#tmpchn,#tmpenu mov #lkpdev,r0 emt 375 bcc 1$ .if eq DEBUG mov #emsg1,r0 jsr pc,error .iff inc errcnt .endc .if ne sp$207 ;.spfun 207 required ; Get Physical Address ; .spfun #5$,#tmpchn,#207,#ethadd-2,#0,#0 1$: mov #5$,r0 emt 375 bcc 3$ .if eq DEBUG mov #emsg8,r0 jsr pc,error .iff inc errcnt .endc .iff ;no .spfun 207 ; Allocate the device ; .spfun #5$,#tmpchn,#200,#ethadd-2,#0,#1 1$: mov #5$,r0 mov #1,6$ emt 375 bcc 2$ .if eq DEBUG mov #emsg2,r0 jsr pc,error .iff inc errcnt .endc ; Deallocate the device ; .spfun #5$,#tmpchn,#200,#ethadd-2,#0,#0 2$: mov #5$,r0 clr 6$ emt 375 bcc 3$ .if eq DEBUG mov #emsg3,r0 jsr pc,error .iff inc errcnt .endc .endc ; Close the channel 3$: .close #tmpchn 4$: mov #ethadd,r0 ;return the ethernet address mov c$pmtr(r5),r1 mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0),(r1) .if eq DEBUG rts pc .iff jmp enexit .endc .if ne sp$207 ;.spfun 207 required ; .spfun #5$,#tmpchn,#207,#ethadd-2,#0,#0 5$: .byte tmpchn,32 .word 0 ;blk .word ethadd-2 ;buf .word 0 ;wcnt .byte 377,207 .word 0 .iff ;no .spfun 207 ; .spfun #5$,#tmpchn,#200,#ethadd-2,#0,(#0 or #1) 5$: .byte tmpchn,32 6$: .word 0 ;blk .word ethadd-2 ;buf .word 0 ;wcnt .byte 377,200 .word 0 .endc ; .lookup #lkpdev,#tmpchn,#tmpenu lkpdev: .byte tmpchn,1 .word tmpenu .word 0 .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 ; .lookup #8$,enchan(r2),endev(r2) 1$: mov #8$,r0 movb enchan(r2),(r0) mov endev(r2),2(r0) emt 375 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 #9$,enchan(r2),#200,#ethadd-2,#0,#1 mov #9$,r0 movb enchan(r2),(r0) emt 375 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 #10$,enchan(r2),#202,#ethsts,#0,#1 mov #10$,r0 movb enchan(r2),(r0) emt 375 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 #11$,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn mov #11$,r0 movb enchan(r2),(r0) mov enbufr(r2),4(r0) mov enpkts(r2),6(r0) emt 375 bcc 5$ .if eq DEBUG mov #emsg6,r0 jsr pc,error .iff inc errcnt .endc ; Enable Frame queueing 5$: .if ne sp$206 ;.spfun 206 required bit #en.que,enflgs(r2) beq 6$ ; .spfun #12$,enchan(r2),#206,#ethsts,#0,#1 mov #12$,r0 movb enchan(r2),(r0) emt 375 bcc 6$ .if eq DEBUG mov #emsg7,r0 jsr pc,error .iff inc errcnt .endc .endc 6$: add #ENTLEN,r2 tst (r2) beq 7$ jmp 1$ 7$: mov errcnt,r0 ;exit status .if eq DEBUG rts pc .iff jmp enexit .endc ; .lookup #8$,enchan(r2),endev(r2) 8$: .byte 0,1 .word 0 .word 0 ; .spfun #9$,enchan(r2),#200,#ethadd-2,#0,#1 9$: .byte 0,32 .word 1 ;blk .word ethadd-2 ;buf .word 0 ;wcnt .byte 377,200 .word 0 ; .spfun #10$,enchan(r2),#202,#ethsts,#0,#1 10$: .byte 0,32 .word 1 ;blk .word ethsts ;buf .word 0 ;wcnt .byte 377,202 .word 0 ; .spfun #11$,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn 11$: .byte 0,32 .word 0 ;blk .word 0 ;buf .word 0 ;wcnt .byte 377,205 .word cmpltn .if ne sp$206 ;.spfun 206 required ; .spfun #12$,enchan(r2),#206,#ethsts,#0,#1 12$: .byte 0,32 .word 1 ;blk .word ethsts ;buf .word 0 ;wcnt .byte 377,206 .word 0 .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$ rts pc .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 rts pc 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 rts pc .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 #4$,enchan(r2),#204,r3,r1,#0 mov #4$,r0 movb enchan(r2),(r0) mov r3,4(r0) mov r1,6(r0) emt 375 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 rts pc .iff jmp enexit .endc ; .spfun #4$,enchan(r2),#204,r3,r1,#0 4$: .byte 0,32 .word 0 ;blk .word 0 ;buf .word 0 ;wcnt .byte 377,204 .word 0 .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 #2$,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn mov #2$,r0 movb enchan(r2),(r0) mov enbufr(r2),4(r0) mov enpkts(r2),6(r0) emt 375 bcc 1$ .if eq DEBUG mov #emsg6,r0 jsr pc,error .iff inc errcnt .endc 1$: .if eq DEBUG rts pc .iff jmp enexit .endc ; .spfun #2$,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn 2$: .byte 0,32 .word 0 ;blk .word 0 ;buf .word 0 ;wcnt .byte 377,205 .word cmpltn .page .sbttl Receive Completion Routine cmpltn: bic #chnmsk,r1 ; compute packet pointer mul #ENTLEN,r1 ; from channel number add #setup,r1 mov pkiptr,r0 mov r1,pktlst(r0) ; put entry into packet list add #2,r0 bic #pktmsk,r0 mov r0,pkiptr jsr pc,resume ;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$: rts pc ;return .endc .if eq DEBUG error: inc errcnt ;update error counter mov r0,-(sp) .print #iomsg mov (sp)+,r0 .print ;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