.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 three EN units: ; ; 0 - recv protocol = EIP ; 1 - recv protocol = EARP ; 2 - ; 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 = 285. ;maximum output packet size TCPPKT = 285. ;buffer length required for a ;512 byte CREDIT TCP packet ARPPKT = 290. ;buffer length required ;for an arp packet ERRBYT = 52 ;IO error byte EARP = 003010 ;0x0608 ;protocols EIP = 000010 ;0x0008 SEARP = 004006 ;0x0806 ;swapped protocols 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/ en3: .rad50 /EN3EN3EN3EN3/ .if ne sp$207 ;.spfun 207 required tmpenu =: en0 ;temporary unit .iff en2: .rad50 /EN2EN2EN2EN2/ ;temporary tmpenu =: en2 ;temporary unit .endc tmpchn =: 12 ;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 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 = ^C1 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 .psect c$code .page .sbttl Get Ethernet Address ; ; engetaddr(s); char *s ; engetaddr:: jsr r5,csv$ mov #ethadd,r0 ;check for the ethernet address mov (r0)+,r1 bis (r0)+,r1 bis (r0),r1 bne 1$ ;have one ! ; Lookup the device and assign a channel ; .lookup #lkpdev,#tmpchn,#tmpenu mov #lkpdev,r0 emt 375 .if ne sp$207 ;.spfun 207 required ; Get Physical Address ; .spfun #2$,#tmpchn,#207,#ethadd-2,#0,#0 mov #2$,r0 emt 375 .iff ;no .spfun 207 ; Allocate the device ; .spfun #2$,#tmpchn,#200,#ethadd-2,#0,#1 mov #2$,r0 mov #1,3$ emt 375 ; Deallocate the device ; .spfun #2$,#tmpchn,#200,#ethadd-2,#0,#0 mov #2$,r0 clr 3$ emt 375 .endc ; Close the channel .close #tmpchn 1$: mov #ethadd,r0 ;return the ethernet address mov c$pmtr(r5),r1 mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0),(r1) rts pc .if ne sp$207 ;.spfun 207 required ; .spfun #2$,#tmpchn,#207,#ethadd-2,#0,#0 2$: .byte tmpchn,32 .word 0 ;blk .word ethadd-2 ;buf .word 0 ;wcnt .byte 377,207 .word 0 .iff ;no .spfun 207 ; .spfun #2$,#tmpchn,#200,#ethadd-2,#0,(#0 or #1) 2$: .byte tmpchn,32 3$: .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$ clr -(sp) ;error count mov #setup,r2 ;set up table ; Lookup the device and assign a channel ; .lookup #7$,enchan(r2),endev(r2) 1$: mov #7$,r0 movb enchan(r2),(r0) mov endev(r2),2(r0) emt 375 bcc 2$ inc (sp) ; Allocate the device 2$: bit #en.alc,enflgs(2) beq 3$ ; .spfun #8$,enchan(r2),#200,#ethadd-2,#0,#1 mov #8$,r0 movb enchan(r2),(r0) emt 375 bcc 3$ inc (sp) ; Set up the receiver protocols 3$: bit #en.prt,enflgs(r2) beq 4$ clr ethsts mov enprot(r2),ethsts+2 ;load protocol ; .spfun #9$,enchan(r2),#202,#ethsts,#0,#1 mov #9$,r0 movb enchan(r2),(r0) emt 375 bcc 4$ inc (sp) ; Start up the designated receivers 4$: bit #en.rcv,enflgs(r2) beq 5$ ; .spfun #10$,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn mov #10$,r0 movb enchan(r2),(r0) mov enbufr(r2),4(r0) mov enpkts(r2),6(r0) emt 375 bcc 5$ inc (sp) ; Enable Frame queueing 5$: .if ne sp$206 ;.spfun 206 required bit #en.que,enflgs(r2) beq 6$ ; .spfun #11$,enchan(r2),#206,#ethsts,#0,#1 mov #11$,r0 movb enchan(r2),(r0) emt 375 bcc 6$ inc (sp) .endc 6$: add #ENTLEN,r2 tst (r2) bne 1$ mov (sp)+,r0 ;exit status rts pc ; .lookup #7$,enchan(r2),endev(r2) 7$: .byte 0,1 .word 0 .word 0 ; .spfun #8$,enchan(r2),#200,#ethadd-2,#0,#1 8$: .byte 0,32 .word 1 ;blk .word ethadd-2 ;buf .word 0 ;wcnt .byte 377,200 .word 0 ; .spfun #9$,enchan(r2),#202,#ethsts,#0,#1 9$: .byte 0,32 .word 1 ;blk .word ethsts ;buf .word 0 ;wcnt .byte 377,202 .word 0 ; .spfun #10$,enchan(r2),#205,enbufr(r2),enpkts(r2),#0,#cmpltn 10$: .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 #11$,enchan(r2),#206,#ethsts,#0,#1 11$: .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$ .if ne sp$211 ;.spfun 211 required ; .spfun #2$,#13,#211,#ethsts,#0,#0 mov #2$,r0 ;abort job i/o emt 375 ;SJ - Monitors .endc 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 .if ne sp$211 ;.spfun 211 required ; .spfun #2$,enchan(r2),#206,#ethsts,#0,#1 2$: .byte 13,32 ;use xmit channel .word 0 ;blk .word ethsts ;buf .word 0 ;wcnt .byte 377,211 .word 0 .endc .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$ 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 3$: mov (r3),r0 ;return i/o status rts pc ; .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$ 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 1$: rts pc ; .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 beq 1$ ; channel 10 mov #ENTLEN,r1 ; channel 11 1$: 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 .end