diff --git a/src/dcg/-read-.-this- b/src/dcg/-read-.-this- new file mode 100644 index 00000000..a11fb12c --- /dev/null +++ b/src/dcg/-read-.-this- @@ -0,0 +1 @@ +Files to support an Ethernet interface, from Dave Conroy's ITS. diff --git a/src/dcg/arp.4 b/src/dcg/arp.4 new file mode 100644 index 00000000..31c2f803 --- /dev/null +++ b/src/dcg/arp.4 @@ -0,0 +1,201 @@ +;ARP/ETH TABLE MANAGEMENT (CALLED BY ETH) +;DGC 14-SEP-2014 + +NAI==2 +NAO==10 + +EBLK + +;INBOUND (REMOTE TO LOCAL) ARP TABLE (AIIA[X] NON-0 => IN USE) +AIIA: BLOCK NAI ;00..31, HW FMT +AIEA0: BLOCK NAI ;00..31, HW FMT +AIEA1: BLOCK NAI ;32..47, HW FMT + +;OUTBOUND (LOCAL TO REMOTE) ARP TABLE (AOIA[X] NON-0 => IN USE) +AOIA: BLOCK NAO ;00..31, HW FMT +AOEA0: BLOCK NAO ;00..31, HW FMT +AOEA1: BLOCK NAO ;32..47, HW FMT +AOSTS: BLOCK NAO ;<0 SEND-REQ, 0 WAIT-ACK, >0 VALID +AOCLK: BLOCK NAO ;IN 0.5 SECOND TICKS +AOCNT: BLOCK NAO ;RETRY COUNT FOR WAIT-ACK + +BBLK + +;CALLED TO INITIALIZE (FLUSH) THE ARP TABLES +;ONLY THE AIIA/AOIA ENTRIES NEED TO BE SET TO 0, BECAUSE IF THESE +;ENTRIES ARE 0, NOTHING ELSE IN THE TABLE MATTERS AT ALL +;AN ARPCLK IN THE MIDDLE IF THIS IS HARMLESS (AND ETHINI KNOWS THIS) +ARPINI: MOVSI H,-NAI +AINI0: SETZM AIIA(H) ;FREE + AOBJN H,AINI0 + MOVSI H,-NAO +AINI1: SETZM AOIA(H) ;FREE + AOBJN H,AINI1 + POPJ P, + +;CALLED FROM NETCLK EVERY 0.5 SECOND TO AGE ENTRIES +;IN THE OUTBOUND ARP TABLE AND TO REQUEST RETRIES AT THE APPROPRIATE +;TIME. RAISES PI LEVEL TO PROTECT THE ARP TABLES FROM DEVICE PI. +ARPCLK: CONI PI,TT ;TT = SPL(NETLVL) + CONO PI,NETOFF + MOVSI H,-NAO +ACLK0: SKIPN AOIA(H) + JRST ACLK3 ;FREE + SKIPE AOCLK(H) + SOSE AOCLK(H) + JRST ACLK3 ;NOT END-OF-LIFE +;IF A VALID ENTRY HAS EA0/EA1=0/0 (ARP FAIL) FLUSH IT AT END-OF-LIFE + SKIPG AOSTS(H) + JRST ACLK1 ;NOT VALID + SKIPN AOEA0(H) + SKIPE AOEA1(H) + JRST ACLK3 + SETZM AOIA(H) ;FREE + JRST ACLK3 +;IF A WAIT-ACK ENTRY STILL HAS RETRIES MAKE IT A SEND-REQ +;OTHERWISE MAKE IT VALID, BUT WITH EA0/EA1=0/0, AND A 5 SEC TIME-TO-LIVE (SO +;THAT A PKT ALREADY IN THE XMQ, OR ONE THAT ARRIVES SOON, IS THROWN AWAY) +ACLK1: SKIPE AOSTS(H) + JRST ACLK3 ;NOT WAIT-ACK + PUSHJ P,ETHIOS ;ALWAYS GET OUTPUT SIDE RUNNING + SOSN AOCNT(H) + JRST ACLK2 ;NO MORE WAIT-ACK RETRIES + SETOM AOSTS(H) ;MAKE SEND-REQ + JRST ACLK3 +ACLK2: SETZM AOEA0(H) ;0/0 (ARP FAIL) + SETZM AOEA1(H) + MOVEI T,1 ;MAKE VALID + MOVEM T,AOSTS(H) + MOVEI T,2.*5. ;LIVE FOR 5 SEC + MOVEM AOCLK(H) +ACLK3: AOBJN H,ACLK0 + ANDI TT,177 ;SPLX(TT) + CONO PI,PICON(TT) + POPJ P, + +;CALLED TO FIND AN IA->EA MAPPING IN THE OUTBOUND ARP TABLE +;ON ENTRY C HOLDS THE IA (HW FMT) THAT NEEDS TO BE FOUND +;RTN+1 NOT FOUND +;RTN+2 FOUND, BUT WAITING FOR ARP-ACK +;RTN+3 FOUND, D/E IS EA0/EA1 (WHICH MIGHT BE 0/0) +ARPFND: MOVSI H,-NAO +AFND0: SKIPE T,AOIA(H) ;FIND IA + CAME C,T + AOBJN H,AFND0 + JUMPGE H,AFND2 ;NOT FOUND, RTN+1 + AOS (P) + SKIPG AOSTS(H) ;VALID ? + JRST AFND2 ;NO, RTN+2 + AOS (P) + MOVE D,AOEA0(H) ;GOT EA0/EA1, RTN+3 + MOVE E,AOEA1(H) + JUMPN D,AFND1 ;LIVE FOR (ANOTHER) 60 MIN + JUMPE E,AFND2 ;IF EA0/EA1 NOT 0/0 +AFND1: MOVEI T,2.*60.*60. + MOVEM T,AOCLK(H) +AFND2: POPJ P, + +;CALLED TO ADD AN ENTRY TO THE OUTBOUND ARP TABLE +;THE STS/CLK/CNT ARE RESET, IN ANTICIPATION OF CALLER SENDING AN ARP-REQ +;ON ENTRY C HOLDS THE IA (HW FMT) THAT NEEDS TO BE ADDED (WHICH IS +;ASSUMED TO NOT BE IN THE OUTBOUND ARP TABLE; THE CALLER HAS CHECKED) +;RTN+1 CAN'T ADD AN ENTRY TO THE TABLE +;RTN+2 ENTRY ADDED TO THE TABLE +ARPADD: SETZ TT, ;OLDEST (GE => NO OLDEST) + MOVSI H,-NAO +AADD0: SKIPN AOIA(H) ;IS THIS A FREE ENTRY ? + JRST AADD2 ;YES, RECYCLE + SKIPG AOSTS(H) ;VALID ? + JRST AADD1 ;NO, LEAVE ALONE + SKIPN T,AOCLK(H) ;IS THIS A FULLY AGED ENTRY ? + JRST AADD2 ;YES, RECYCLE + SKIPGE TT ;IF NO OLDEST OR NEW ENTRY + CAMGE T,AOCLK(TT) ;OLDER THAN THE CURRENT OLDEST ? + MOVE TT,H ;YES, NEW OLDEST +AADD1: AOBJN H,AADD0 + SKIPL H,TT ;FOUND A REUSABLE OLDEST ? + JRST AADD3 ;NO, RTN+1 +AADD2: MOVEM C,AOIA(H) ;FILL IN NEW ENTRY + SETZM AOSTS(H) ;WAIT-ACK + MOVEI T,2.*5. ;WAIT 5 SEC FOR ACK + MOVEM T,AOCLK(H) + MOVEI T,2. ;2 TRIES + MOVEM T,AOCNT(H) + AOS (P) ;RTN+2 +AADD3: POPJ P, + +;CALLED TO CHECK IF AN ARP-REQ FROM OUTBOUND IS NEEDED +;THE STS/CLK ARE RESET, IN ANTICIPATION OF CALLER SENDING AN ARP-REQ (CNT +;IS LEFT ALONG, BECAUSE IT IS BEING USED TO COUNT THE RETRIES) +;RTN+1 NO ARP-REQ NEEDED +;RTN+2 ARP-REQ NEEDED, C IS IA (HW FMT) +ARPORQ: MOVSI H,-NAO +AORQ0: SKIPE C,AOIA(H) ;FIND NON-FREE ENTRY + SKIPL AOSTS(H) ;IN STATE SEND-REQ (<0) + AOBJN H,AORQ0 + JUMPGE H,AORQ1 ;NO NON-FREE ENTRY, RTN+1 + SETZM AOSTS(H) ;WAIT-ACK + MOVEI T,2.*5. ;WAIT 5 SEC FOR ACK + MOVEM T,AOCLK(H) + AOS (P) ;RTN+2 +AORQ1: POPJ P, + +;CALLED TO CHECK IF AN ARP-ACK FROM INBOUND IS NEEDED +;RTN+1 NO ARP-ACK NEEDED +;RTN+2 ARP-ACK NEEDED, C IS IA (HW FMT), D/E IS EA0/EA1 (HW FMT) +ARPOAK: MOVSI H,-NAI +AOAK0: SKIPN C,AIIA(H) ;FIND NON-FREE ENTRY + AOBJN H,AOAK0 + JUMPGE H,AOAK1 ;NO NON-FREE ENTRY, RTN+1 + SETZM AIIA(H) ;FREE + MOVE D,AIEA0(H) + MOVE E,AIEA1(H) + AOS (P) ;RTN+2 +AOAK1: POPJ P, + +;CALLED TO PROCESS AN ARP-REQ THAT HAS BEEN RECEIVED +;ON ENTRY A/B HOLD THE FIRST TWO WORDS OF THE ARP PKT (WHICH ARE UNUSED +;BUT WHICH NEED TO BE PRESERVED), C HOLDS THE ARC IA (HW FMT), AND +;D/E HOLD THE SRC EA0/EA1 (FOR WHICH THERE ISN'T A SW FMT) +ARPIRQ: MOVSI H,-NAI +AIRQ0: SKIPE AIIA(H) ;FIND FREE ENTRY + AOBJN H,AIRQ0 + JUMPGE H,AIAK2 ;NO FREE ENTRY, DONE + MOVEM C,AIIA(H) ;SRC IA + MOVEM D,AIEA0(H) ;SRC EA + MOVEM E,AIEA1(H) +;IF A REMOTE HOST ASKS FOR MY EA, IT WANTS TO SEND ME SOMETHING, +;AND THERE IS A GOOD CHANCE THAT I WILL WANT TO SEND SOMETHING BACK, SO IF +;IT'S EASY, SAVE THE IA/EA OF THE REMOTE HOST IN THE OUTBOUND ARP TABLE + MOVSI H,-NAO +AIRQ1: SKIPE T,AOIA(H) ;ALREADY KNOWN ? + CAME C,T + AOBJN H,AIRQ1 + JUMPL H,AIAK2 ;YES, DONE + MOVSI H,-NAO +AIRQ2: SKIPN AOIA(H) ;NO, LOOK FOR A FREE ENTRY + JRST AIRQ3 + SKIPLE AOSTS(H) ;OR A VALID ENTRY THAT HAS AGED OUT + SKIPE AOCLK(H) + AOBJN H,AIRQ2 +AIRQ3: JUMPGE H,AIAK2 ;NO ENTRY, DONE + MOVEM C,AOIA(H) ;SRC IA + JRST AIAK1 ;FINISH IN COMMON CODE + +;CALLED TO PROCESS AN ARP-ACK THAT HAS BEEN RECEIVED +;ON ENTRY A/B HOLD THE FIRST TWO WORDS OF THE ARP PKT (WHICH ARE UNUSED +;BUT WHICH NEED TO BE PRESERVED), C HOLDS THE ARC IA (HW FMT), AND +;D/E HOLD THE SRC EA0/EA1 (FOR WHICH THERE ISN'T A SW FMT) +ARPIAK: MOVSI H,-NAO +AIAK0: SKIPE T,AOIA(H) ;FIND MATCH + CAME C,T + AOBJN H,AIAK0 + JUMPGE H,AIAK2 ;NO ENTRY, IGNORE +;ARPIRQ/ARPIAK COME HERE TO FINISH FILLING IN AN OUTBOUND ARP TABLE ENTRY +AIAK1: MOVEM D,AOEA0(H) ;SRC EA + MOVEM E,AOEA1(H) + MOVEI T,1 ;VALID + MOVEM T,AOSTS(H) + MOVEI T,2.*60.*60. ;LIVE FOR 60 MIN + MOVEM T,AOCLK(H) +AIAK2: POPJ P, diff --git a/src/dcg/kxeth.11 b/src/dcg/kxeth.11 new file mode 100644 index 00000000..98932c28 --- /dev/null +++ b/src/dcg/kxeth.11 @@ -0,0 +1,701 @@ +;ETH INTERFACE, PDP-10/X (KX) USING WIZNET W5300 +;DGC 26-DEC-2014 + +;IF KXETH IS IN THE CONFIG, IT BETTER BE DOING SOMETHING +IFE INETHP\CHETHP,.ERR KXETH DOING NOTHING + +ETH==600 ;DEVICE ADDRESS + +EBCEA0==777777777760 ;BROADCAST HARDWARE ADDRESS +EBCEA1==777774000000 ;FF:FF:FF:FF:FF:FF + +NPDLX==64. ;SIZE OF PDL (ETHLVL) + +EBLK + +ETHUP: 0 ;<0 UP, >=0 DOWN/DEAD + +EOBSY: 0 ;<0 BUSY, >=0 IDLE +EOSAV: 0 ;SAVED PKT +EOCHS: 0 ;SAVED PKT TYPE (<0 CHAOS, >=IP) +EACS: BLOCK 16. ;AC SAVE AREA (ETHLVL) +EPDLX: BLOCK NPDLX ;PDL (ETHLVL) + +BBLK + +IFN INETHP,[ +;ORIGINALLY THE NETHST AND NETIMP SYSTEM CALLS WERE ONLY FOR IMP, +;BUT NETHST WITH ARG1 OF -1 IS HOW THE NETWRK LIBRARY EXPECTS TO BE ABLE TO +;GET THE INET ADDRESS OF THE LOCAL SYSTEM, SO ETH INCLUDES A VERSION OF +;NETHST THAT CAN HANDLE THIS CASE (AND ONLY THIS CASE) +;NOTE THAT WE JUST RETURN ETHUP3 AS VAL2, EVEN THOUGH VAL2 IS ACTUALLY IN +;HOSTS2 FORMAT, SIMPLY ASSUMING THAT DOING SO WON'T BE TROUBLESOME +ANETHST:HRRE T,A ;HW -1 => FW -1 + AOJN T,OPNL25 ;ONLY ALLOW ARG1 OF -1 (LOCAL HOST) + MOVEI A,0 ;4.2-4.1-00 (DOWN), NO REASON + SKIPGE ETHUP + TLO A,2000 ;4.2-4.1=10 (UP) + MOVE B,[ETHUS3] + JRST POPJ1 +] + +IFN CHETHP,[ +;THESE TABLES ARE USED TO MAP A CHAOS ADDRESS (FOUND IN ECHCA) INTO +;A MATCHING INET ADDRESS (FOUND IN THE MATCHING ENTRY IN ECHIA). TABLE LOOKUP +;SEEMS LIKE THE BEST SCHEME, ALTHOUGH IT MIGHT BE BETTER TO MAP CHAOS +;NETWORKS INTO INET NETWORKS, RATHER THAN CHAOS ADDRESSES INTO INET ADDRESSES, +;IF SOME FUTURE VERSION OF KXETH TRIES TO DO SOMETHING WITH BRD PKTS. +ECHCA: 402 ;TX (1.2) + 403 ;N1 (1.3) +NECHCA=.-ECHCA +ECHIA: IPADDR 192,168,1,2 ;TX.LOCAL + IPADDR 192,168,1,3 ;UBUNTU-NUC-01.LOCAL +NECHIA=.-ECHIA +IFN NECHCA-NECHIA,.ERR ECHCA/ECHIA LENGTH MISMATCH +] + +;CALLED (SYSJOB) WHEN THE SYSTEM IS STARTED +;CHECK TO SEE IF A W5300 IS ATTCHED TO THE ETH, AND IF IT IS, +;INITIALIZE THE W5300, TURN ON THE PI, AND MARK IT AS UP. +;THIS ROUTINE CAN BE CALLED AT ANY TIME, EVEN THOUGH THE SYSTEM CURRENTLY +;DOES NOT DO SO (THE SYSJOB COULD BE MODIFIED SO THAT "LOCK NET" +;CALLED ETHINI AND DID THE SAME THING ON ETH AS IT CURRENTLY DOES ON IMP). +ETHINI: CONO ETH,0 ;DISABLE ETH PI + SETZM ETHUP ;MARK AS DOWN/DEAD + PUSHJ P,ARPINI ;CLEAR OUT THE ARP TABLES + SETZM EOBSY ;MARK AS IDLE + SKIPN A,EOSAV ;A <- SAVED PKT + JRST EINI1 + SETZM EOSAV + SKIPGE EOCHS ;CHECK THE SAVED PKT TYPE + JRST EINI0 ;CHAOS +IFE INETHP,[ +;WE HAVE AN IP PKT, BUT INETHP ISN'T TRUE. CAN'T HAPPEN. + BUG HALT,[ETHINI-INETHP] +] +IFN INETHP,[ + PUSHJ P,EIPFR ;FREE IP PKT + JRST EINI1 +] +IFE CHETHP,[ +;WE HAVE A CHAOS PKT, BUT CHETHP ISN'T TRUE. CAN'T HAPPEN. +EINI0: BUG HALT,[ETHINI-CHETHP] +] +IFN CHETHP,[ +EINI0: PUSHJ P,ECHFR ;FREE CHAOS PKT +] +;RESET SOME POSSIBLE W5300, THEN LOOK TO SEE IF IT'S THERE +;THE (BADLY DOCUMENTED) PB FLAG TELLS THE W5300 NOT TO RESPOND TO ICMP ECHO PKTS +EINI1: DATAO ETH,[161000,,0] ;MR <- WDF2, WDF1, WDF0, RST + MOVE T,TIME ;1-2 TICK (32-64MS) DELAY TO ENSURE + ADDI T,2 ;PLL LOCKED (10MS IS ENOUGH) + CAMLE T,TIME + PUSHJ P,UFLS + DATAO ETH,[160104,,0] ;MR <- WDF2, WDF1, WDF0, PB, IND + DATAO ETH+4*1,[001770,,0] ;AR <- IDR + DATAI ETH+4*2,T + CAME T,[246000000000] + JRST EINI2 ;NO W5300 +;W5300 IS THERE, ENABLE SOCKET 0 INTERRUPTS, LOAD HARDWARE ADDRESS + DATAO ETH+4*1,[000020,,0] ;IMR <- S0INT + DATAO ETH+4*2,[000004,,0] + DATAO ETH+4*1,[000040,,0] ;SHAR <- ETHEA0/ETHEA1 + DATAO ETH+4*2,[ETHEA0&777774000000] + DATAO ETH+4*1,[000050,,0] + DATAO ETH+4*2,[&777774000000] + DATAO ETH+4*1,[000060,,0] + DATAO ETH+4*2,[ETHEA1&777774000000] +;ALLOCATE ALL OF THE PKT MEMORY TO SOCKET 0 (8K TO TX, 120K TO RX) + DATAO ETH+4*1,[000200,,0] ;TMS01R <- 8K/0K + DATAO ETH+4*2,[020000,,0] + DATAO ETH+4*1,[000210,,0] ;TMS23R <- 0K/0K + DATAO ETH+4*2,[000000,,0] + DATAO ETH+4*1,[000220,,0] ;TMS45R <- 0K/0K + DATAO ETH+4*2,[000000,,0] + DATAO ETH+4*1,[000230,,0] ;TMS67R <- 0K/0K + DATAO ETH+4*2,[000000,,0] + DATAO ETH+4*1,[000240,,0] ;RMS01R <- 120K/0K + DATAO ETH+4*2,[360000,,0] + DATAO ETH+4*1,[000250,,0] ;RMS23R <- 0K/0K + DATAO ETH+4*2,[000000,,0] + DATAO ETH+4*1,[000260,,0] ;RMS45R <- 0K/0K + DATAO ETH+4*2,[000000,,0] + DATAO ETH+4*1,[000270,,0] ;RMS67R <- 0K/0K + DATAO ETH+4*2,[000000,,0] + DATAO ETH+4*1,[000300,,0] ;MTYPER <- 1 + DATAO ETH+4*2,[000004,,0] +;ENABLE SOCKET 0 IN LOW-LEVEL ETHERNET (MACRAW) MODE + DATAO ETH+4*1,[004020,,0] ;S0IMR <- SENDOK, RECV + DATAO ETH+4*2,[000120,,0] + DATAO ETH+4*1,[004000,,0] ;S0MR <- MF, MACRAW + DATAO ETH+4*2,[000420,,0] + DATAO ETH+4*1,[004010,,0] ;S0CR <- OPEN + DATAO ETH+4*2,[000004,,0] + DATAO ETH+4*1,[004040,,0] ;SOCK_MACRAW + DATAI ETH+4*2,T + TLZ T,776000 + CAME T,[000410000000] + BUG HALT,[NOT SOCK_MACRAW] + SETOM ETHUP ;MARK AS UP + CONO ETH,20+ETHCHN ;ENABLE ETH PI ON ETHCHN +EINI2: POPJ P, + +IFN INETHP,[ +;CALLED TO FREE THE IP PKT BUF POINTED TO BY A +;IPIODN ONLY USES T/Q, SO THE OLD LEVEL CAN BE HELD IN TT OVER THE CALL +;PKQPF/PKQBL LOOK LIKE THEY PROTECT THEMSELVES, SO IS THIS NEEDED ? +EIPFR: CONI PI,TT ;TT <- SPL(NETLVL) + CONO PI,NETOFF + MOVSI T,(%PKPIL) ;CLR PI-LEVEL LOCK, FREE PKT + ANDCAM T,PK.FLG(A) + PUSHJ P,IPIODN + ANDI TT,177 ;SPLX(TT) + CONO PI,PICON(TT) + POPJ P, +] + +IFN CHETHP,[ +;CALLED TO FREE THE CHAOS PKT BUF POINTED TO BY A +;THERE IS NO NEED TO HACK PI LEVELS BECAUSE CHABRT DOES A PIOFF/PION +ECHFR: HRROS T,-2(A) ;NOT ON TX LIST (LH=1'S) + AOJN T,ECHFR0 ;IN ANY LIST (LH=1'S, RH=1'S) ? + PUSHJ P,CHABRT ;NO, RETURN TO FREE +ECHFR0: POPJ P, +] + +;CALLED (MANY PLACES) TO ENSURE THE OUTPUT SIDE IS RUNNING +;BECAUSE THIS CAN BE CALLED AT MAIN LEVEL AND AT DIFFERENT PI LEVELS IT +;SIMPLY MAKES A SW REQ AND LETS ETHBRK DO ALL THE REAL WORK +;THIS MUST NOT BE CALLED IF ETHUP>=0 (DOWN/DEAD) BECAUSE ETHBRK DOES NOT CHECK +ETHIOS: CONO PI,4000\<200_-ETHCHN> + POPJ P, + +;CALLED FROM THE JSR IN LOCATION 40+2*ETHCHN (ETHCHN=6) +;ONLY S0_INT.RECV AND S0_INT.SENDOK SHOULD BE ENABLED IN THE W5300 +;NOTE THAT BECAUSE ETHLVL IS LOWER PRIORITY THAN NETLVL CARE MUST BE TAKEN +;WHEN THIS CODE CALLS INTO ANY OF THE COMMON NETWORKING CODE +EBLK +ETHBRK: 0 +BBLK + MOVEM 17,EACS+17 ;SAVE REGS + MOVEI 17,EACS + BLT 17,EACS+16 + MOVE P,[-NPDLX,,EPDLX-1] ;SET UP ETHLVL'S PDL + CONO PI,20000\<200_-ETHCHN> ;CLR (POSSIBLE) SW REQ ON ETHCHN + DATAO ETH+4*1,[004030,,0] ;T <- S0_IR + DATAI ETH+4*2,T + TLNN T,120 ;RECV OR SENDOK REQ ? + JRST EBRK0 ;NO + DATAO ETH+4*2,T ;CLEAR REQ + TLNE T,100 ;SENDOK, MARK OUTPUT IDLE + SETZM EOBSY + TLNE T,20 ;RECV, INPUT PKTS + PUSHJ P,EIPKT +EBRK0: SKIPL EOBSY ;IF IDLE, TRY AND OUTPUT PKTS + PUSHJ P,EOPKT + MOVSI 17,EACS ;RESTORE REGS + BLT 17,17 + JRST 12,@ETHBRK ;DISMISS PI, RETURN + +;CALLED (ETHBRK) TO INPUT ALL PKTS IN FIFO +;ARP-REQ AND ARP-ACK PACKETS UPDATE THE ARP TABLES, WHICH MAY HAVE +;THE SIDE EFFECT OF UNBLOCKING THE OUTPUT SIDE +;INET PKTS ARE INPUT, AND FED EITHER TO THE CHAOS STACK (IF THE PROTOCOL +;TYPE IS THAT OF A CHAOS PKT) OR TO THE INET STACK (DEFAULT). +;CHAOS PKTS ARE PROCESSED USING DO-IT-YOURSELF INET CODE BECAUSE IT'S +;LEGAL TO CONFIGURE CHAOS WITHOUT CONFIGURING INET. +;THIS ROUTINE CAN SMASH ALL THE ACS BECAUSE IT'S REALLY JUST A PART OF ETHBRK. +EIPKT: DATAO ETH+4*1,[004250,,0] ;T <- S0_RX_RSR0:S0_RX_RSR2 + DATAI ETH+4*2,T + LSH T,-20. + DATAO ETH+4*1,[004240,,0] + DATAI ETH+4*2,TT + TLNE TT,4 + TRO T,200000 + JUMPE T,EIPKT9 ;0 => DONE + DATAO ETH+4*1,[004300,,0] ;S0_RX_FIFOR + DATAI ETH+4*2,R ;R <- 2-BYTE PKT SIZE + LSH R,-20. +;PULL THE DST-EA AND SRC-EA OUT OF THE RX FIFO + CAIGE R,12. ;ENOUGH FOR 2*ETHADDR + JRST EIPKT6 ;NO, FLUSH + SUBI R,12. + DATAI ETH+4*10+4*2,A ;A/B <- PKT DST ETHADDR + DATAI ETH+4*2,B + DATAI ETH+4*10+4*2,T ;PKT SRC ETHADDR + DATAI ETH+4*2,T +;THIS CHECK IS PURE PARANOIA, SINCE THE HW SHOULD HAVE DONE THE SAME CHECK + CAME A,[ETHEA0] ;DST ETHADDR = ME + JRST EIPKT1 ;NO + CAMN B,[ETHEA1] + JRST EIPKT2 ;YES +EIPKT1: CAME A,[EBCEA0] ;DST ETHADDR = BROADCAST + JRST EIPKT6 ;NO, FLUSH + CAME B,[EBCEA1] + JRST EIPKT6 ;NO, FLUSH +;PULL THE ETHTYPE OUT OF THE RX FIFO +EIPKT2: CAIGE R,2. ;ENOUGH FOR ETHTYPE + JRST EIPKT6 ;NO, FLUSH + SUBI R,2. + DATAI ETH+4*2,A ;A <- ETHTYPE +;CHECK FOR ARP PKTS, AND PROCESS THEM +;WE ONLY UNDERSTAND THE 28-BYTE PKTS THAT MAP AN IP ADDR (V4) TO AN ETH ADDR + CAME A,[20030000000] ;ETHTYPE ARP (HEX 0806) ? + JRST EIPKT3 + CAIGE R,28. ;IS THE PKT LONG ENOUGH ? + JRST EIPKT6 ;NO, FLUSH + SUBI R,28. + DATAI ETH+4*10+4*2,A ;HW TYPE, PROTO TYPE + DATAI ETH+4*10+4*2,B ;HW ADDR LEN, PROTO ADDR LEN, OPER + DATAI ETH+4*10+4*2,D ;SRC-EA, SRC-IA + DATAI ETH+4*2,E + DATAI ETH+4*10+4*2,C + DATAI ETH+4*10+4*2,T ;DST-EA (FLUSHED), DST-IA + DATAI ETH+4*2,T + DATAI ETH+4*10+4*2,I +;AN ETH PKT IS AT LEAST 46 BYTES LONG, SO THERE IS PADDING TO FLUSH + ADDI R,1.+4. ;R <- # OF 16-BIT WORDS (PAD+CRC) + LSH R,-1 +EIPKTM: DATAI ETH+4*2,T ;FLUSH PAD+CRC + SOJG R,EIPKTM + CAME A,[4100000] ;HW-TYPE=0001 (ETH), SW-TYPE=0800 (IP) + JRST EIPKT ;NO, FLUSH + CAME I,[ETHUS3_4] ;IS THE DST-IA MINE (MAINLY FOR ARP-REQ) ? + JRST EIPKT ;NO, FLUSH + CAMN B,[14020000020] ;06, 04, 0001 (ARP-REQ) + PUSHJ P,ARPIRQ + CAMN B,[14020000040] ;06, 04, 0002 (ARP-ACK) + PUSHJ P,ARPIAK + JRST EIPKT +;CHECK FOR IP (V4) PKTS AND PROCESS THEM +EIPKT3: CAME A,[20000000000] ;ETHTYPE IP (HEX 0800) ? + JRST EIPKT6 + CAIGE R,20. ;ENOUGH FOR THE IP HDR ? + JRST EIPKT6 ;NO, FLUSH + SUBI R,12. ;WORDS 0-2 TO C/D/E + DATAI ETH+4*10+4*2,C ;CHOSEN BECAUSE IPGIPT USES A/B + DATAI ETH+4*10+4*2,D + DATAI ETH+4*10+4*2,E +IFN CHETHP,[ +;AN IP PKT WITH A PROTOCOL TYPE OF CHAOS, GETS SENT TO THE CHAOS CODE + LDB T,[241000,,E] ;CHAOS PKT ? + CAIN T,16. + JRST EIPKTA ;YES +] +IFN INETHP,[ +;AN IP PKT; ALLOCATE A PKT BUF, COPY PKT TO BUF, SEND TO IP +;IPGIPT ONLY USES T/Q, SO THE OLD LEVEL CAN BE HELD IN TT OVER THE CALL +;PKQGF/PKBAL LOOK LIKE THEY PROTECT THEMSELVES, SO IS THIS NEEDED ? +;IPRDGM USES JUST ABOUT EVERYTHING, SO THE OLD PI LEVEL IS SAVED ON THE PDL + MOVE A,R ;A <- PKT LEN (WORDS) + ADDI A,12.+3. ;12. BECAUSE 3. WORDS ALREADY READ + LSH A,-2 + CONI PI,TT ;TT <- SPL(NETLVL) + CONO PI,NETOFF + PUSHJ P,IPGIPT ;A <- IP PKT BUF (USES B, T, Q) + MOVEI A,0 ;A <- 0 ON FAILURE (RTN+1) + ANDI TT,177 ;SPLX(TT) + CONO PI,PICON(TT) + JUMPE A,EIPKT6 ;NO PKT BUF, FLUSH + HRRZ T,PK.BUF(A) ;MOVE THE 3 WORDS ALREADY READ + MOVEM C,0(T) ;INTO THE IP PKT BUF + MOVEM D,1(T) + MOVEM E,2(T) + MOVE B,R ;B <- WORDS (AOBJN) + LSH B,-2 + MOVN B,B + HRLZ B,B + HRRI B,3(T) + MOVE C,R ;C <- BYTES (0 - 3) + ANDI C,3 + JUMPGE B,EIPKT5 +EIPKT4: DATAI ETH+4*10+4*2,(B) ;READ WORDS + AOBJN B,EIPKT4 +EIPKT5: XCT EIPKT8(C) ;READ FINAL 0-3 BYTES + DATAI ETH+4*10+4*2,T ;FLUSH 4 BYTE CRC + MOVE B,R ;B <- PKT LEN (WORDS) + ADDI B,12.+3. ;12. BECAUSE 3. WORDS ALREADY READ + LSH B,-2 + MOVEI C,0 ;C <- IP HDR OFFS INTO PKT + CONI PI,T ;PUSH(SPL(NETLVL)) + PUSH P,T + CONO PI,NETOFF + PUSHJ P,IPRDGM ;SEND PKT TO IP STACK + POP P,T ;SPLX(POP()) + ANDI T,177 + CONO PI,PICON(T) + JRST EIPKT +] +;FLUSH UNKNOWN OR MALFORMED PKT (R = DATA LEN IN FIFO) +EIPKT6: ADDI R,1.+4. ;R <- # OF 16-BIT WORDS (DATA + CRC) + LSH R,-1 +EIPKT7: DATAI ETH+4*2,T ;FLUSH DATA + CRC + SOJG R,EIPKT7 + JRST EIPKT +;XCT EIPKT8(C) TO READ THE FINAL 0-3 BYTES OF IP OR NORMAL-CHAOS PKT +EIPKT8: JFCL ;0 + DATAI ETH+4*2,(B) ;1, READ 2, 0XXX + DATAI ETH+4*2,(B) ;2, READ 2, 01XX + DATAI ETH+4*10+4*2,(B) ;3, READ 4, 012X +;RETURN THROUGH HERE +EIPKT9: POPJ P, +IFN CHETHP,[ +;A CHAOS-IN-IP PKT; ALLOCATE A PKT BUF, COPY PKT TO BUF, SEND TO CHAOS +;NO FRAGS BECAUSE 524 BYTES (20+16+488) IS LESS THAN 576 BYTES +;CHABGI PROTECTS ITSELF, SO THERE IS NO NEED TO HACK THE PI LEVELS AT THE CALL +;CHAPII USES JUST ABOUT EVERYTHING, SO THE OLD PI LEVEL IS SAVED ON THE PDL +EIPKTA: SUBI R,8. ;WORDS 3-4 TO I/J + DATAI ETH+4*10+4*2,I + DATAI ETH+4*10+4*2,J + PUSHJ P,EIPCS ;TT <- IP CHECKSUM OF C/D/E/I/J + JUMPN TT,EIPKT6 ;NOT 0, FLUSH + LDB T,[400400,,C] ;IF NOT IP (V4), FLUSH + CAIE T,4 + JRST EIPKT6 +;BROADCASTS CAN BE IGNORED BECAUSE CURRENTLY NOBODY SENDS THEM ON CHAOS +; CAMN J,[>_4] +; JRST EIPKTB +; CAMN J,[37777777777_4] +; JRST EIPKTB + CAME J,[ETHUS3_4] ;IS THIS SENT TO ME ? + JRST EIPKT6 ;NO, FLUSH +EIPKTB: LDB T,[041600,,D] ;IF FRAG, FLUSH + JUMPN T,EIPKT6 + LDB T,[340400,,C] ;IP HEADER LENGTH + SUBI T,5. + JUMPL T,EIPKT6 ;<5 => BAD HDR, FLUSH + JUMPE T,EIPKTD ;=5 => NO OPTIONS + MOVE TT,T + LSH TT,2 + CAMGE R,TT ;ARE THE OPTION WORDS THERE ? + JRST EIPKT6 ;NO, FLUSH + SUB R,TT +EIPKTC: DATAI ETH+4*10+4*2,TT ;EAT OPTION WORDS + SOJG T,EIPKTC +EIPKTD: CAIL R,4*%CPKDT ;LEGAL PKT SIZE ? + CAILE R,<4*%CPKDT>+%CPMXC + JRST EIPKT6 ;NO, FLUSH + PUSHJ P,CHABGI ;A <- CH PKT BUF FROM FREE LIST + JRST EIPKT6 ;NONE, FLUSH + SUBI R,4*%CPKDT + DATAI ETH+4*14+4*2,0(A) ;READ IN PKT HDR, ALWAYS BYTE-SWAPPED + DATAI ETH+4*14+4*2,1(A) + DATAI ETH+4*14+4*2,2(A) + DATAI ETH+4*14+4*2,3(A) + MOVE B,R ;B <- AOBJN WORD, 4-BYTE CHUNKS + LSH B,-2 + MOVN B,B + HRLZ B,B + HRRI B,%CPKDT(A) + MOVE C,R ;C <- 0-3 BYTES AT THE END + ANDI C,3 + PUSHJ P,CHSWAB ;READ PKT IN BYTE-SWAPPED MODE ? + JRST EIPKTG ;RTN+1 => NO, RTN+2 => YES + JUMPGE B,EIPKTF ;READ PKT, BYTE-SWAPPED MODE +EIPKTE: DATAI ETH+4*14+4*2,(B) + AOBJN B,EIPKTE +EIPKTF: XCT EIPKTK(C) + JRST EIPKTJ +EIPKTG: JUMPGE B,EIPKTI ;READ PKT, NORMAL MODE +EIPKTH: DATAI ETH+4*10+4*2,(B) + AOBJN B,EIPKTH +EIPKTI: XCT EIPKT8(C) +EIPKTJ: DATAI ETH+4*10+4*2,T ;FLUSH 4 BYTE CRC +;FLUSH PKT IF SA IS NOT KNOWN, MAKING IT IMPOSSIBLE TO EVER TALK BACK +;ADDING AN NEW ENTRY TO THE ECHCA->ECHIA TABLE MIGHT BE A BETTER THING TO DO + LDB T,[$CPKSA(A)] + MOVSI TT,-NECHCA +EIPKTN: CAME T,ECHCA(TT) ;IS THIS SA KNOWN ? + AOBJN TT,EIPKTN + JUMPL TT,EIPKTO ;YES + PUSHJ P,ECHFR ;FLUSH PKT + JRST EIPKT +;WE KNOW WE CAN TALK BACK, SO SEND THE PKT TO THE CHAOS STACK +EIPKTO: CONI PI,T ;PUSH(SPL(NETLVL)) + PUSH P,T + CONO PI,NETOFF + PUSHJ P,CHAPII ;SEND PKT TO CHAOS + POP P,T ;SPLX(POP()) + ANDI T,177 + CONO PI,PICON(T) + JRST EIPKT +;XCT EIPKTK(C) TO READ THE FINAL 0-3 BYTES OF BYTE-SWAPPED CHAOS PKT +EIPKTK: JFCL ;0 + DATAI ETH+4*2,(B) ;1, READ 2, 0XXX + DATAI ETH+4*4+4*2,(B) ;2, READ 2, 10XX + PUSHJ P,EIPKTL ;3, READ 4, 10X2 -> 102X +EIPKTL: DATAI ETH+4*14+4*2,(B) + LDB T,[041000,(B)] ;THIS ISN'T VERY EFFICIENT, BUT + DPB T,[141000,(B)] ;IT'S ALSO VERY UNCOMMON + POPJ P, +] + +;CALLED (ETHBRK) WHEN THE OUTPUT SIDE IS IDLE TO ENSURE THAT +;THE OUTPUT SIDE IS RUNNING IF THERE IS ACTUALLY SOMETHING THAT CAN BE OUTPUT +;CHAOS PKTS ARE PROCESSED USING DO-IT-YOURSELF INET CODE BECAUSE IT'S +;LEGAL TO CONFIGURE CHAOS WITHOUT CONFIGURING INET. +;THIS ROUTINE CAN SMASH ALL THE ACS BECAUSE IT'S REALLY JUST A PART OF ETHBRK. +;CHECK IF THERE IS AN ARP-ACK THAT NEEDS TO BE SENT +EOPKT: PUSHJ P,ARPOAK ;IS THERE AN ARP-ACK TO OUTPUT ? + JRST EOPKT0 ;NO + DATAO ETH+4*1,[004270,,0] ;S0_TX_FIFOR + DATAO ETH+4*10+4*2,D ;DST ETH ADDR (REMOTE) + DATAO ETH+4*2,E + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC ETH ADDR (ME) + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*2,[20030000000] ;0806 (ARP) + DATAO ETH+4*10+4*2,[4100000] ;0001 (ETH), 0800 (IP) + DATAO ETH+4*10+4*2,[14020000040];06, 04, 0002 (ARP-ACK) + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC ETH/IP ADDRS (ME) + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*10+4*2,[ETHUS3_4] + DATAO ETH+4*10+4*2,D ;DST ETH/IP ADDRS (REMOTE) + DATAO ETH+4*2,E + DATAO ETH+4*10+4*2,C + MOVEI R,12.+2.+28. ;SEND PKT + JRST EOPKTS +;CHECK IF THERE IS AN ARP-REQ THAT NEEDS TO BE SENT (RE-SENT) +EOPKT0: PUSHJ P,ARPORQ ;IS THERE AN ARP-REQ TO OUTPUT ? + JRST EOPKT1 ;NO + DATAO ETH+4*1,[004270,,0] ;S0_TX_FIFOR + DATAO ETH+4*10+4*2,[EBCEA0] ;DST ETH ADDR (BROADCAST) + DATAO ETH+4*2,[EBCEA1] + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC ETH ADDR (ME) + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*2,[20030000000] ;0806 (ARP) + DATAO ETH+4*10+4*2,[4100000] ;0001 (ETH), 0800 (IP) + DATAO ETH+4*10+4*2,[14020000020];06, 04, 0001 (ARP-REQ) + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC ETH/IP ADDRS (ME) + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*10+4*2,[ETHUS3_4] + DATAO ETH+4*10+4*2,[0] ;DST ETH/IP ADDRS (IA=REMOTE, EA=0) + DATAO ETH+4*2,[0] + DATAO ETH+4*10+4*2,C + MOVEI R,12.+2.+28. ;SEND PKT + JRST EOPKTS +;GET A PACKET TO WORK ON, EITHER SAVED FROM LAST TIME, OR FRESH FROM AN XMQ +;IPGXMQ/CHGXMQ ONLY USE T/Q, SO THE OLD LEVEL CAN BE HELD IN TT OVER THE CALL +EOPKT1: SKIPN A,EOSAV ;A <- SAVED PKT + JRST EOPKT2 ;NONE + SETZM EOSAV + SKIPGE B,EOCHS ;B <- SAVED PKT TYPE (<0 CHAOS, >=0 IP) + JRST EOPKT7 ;CHAOS + JRST EOPKT4 ;IP +EOPKT2: CONI PI,TT ;TT <- SPL(NETLVL) + CONO PI,NETOFF +IFN INETHP,[ + PUSHJ P,IPGXMQ ;A <- PKT FROM IPXMQ + MOVEI B,0 ;B <- IP (>=0) + JUMPN A,EOPKT3 +] +IFN CHETHP,[ + PUSHJ P,CHGXMQ ;A <- PKT FROM CHXMQ + MOVNI B,1 ;B <- CHAOS (<0) + JUMPN A,EOPKT3 +] + MOVEI A,0 ;A <- NO PKT +EOPKT3: ANDI TT,177 ;SPLX(TT) + CONO PI,PICON(TT) + JUMPE A,EOPKTX ;NO PKT, RETURN + SKIPGE B + JRST EOPKT7 ;CHAOS +IFE INETHP,[ +;WE HAVE AN IP PKT, BUT INETHP ISN'T TRUE. CAN'T HAPPEN. +EOPKT4: BUG HALT,[EOPKT-INETHP] +] +IFN INETHP,[ +;LOOK UP THE IP IA->EA MAPPING USING ARP +;INET SHOULD HAVE ARRANGED THAT PK.DST(A) IS ON THE LOCAL NET, +;BUT IF IT ISN'T, USE THE GATEWAY (DON'T DISCARD THE PKT OR CRASH THE SYSTEM) +EOPKT4: MOVE T,PK.DST(A) ;T <- DST IA (SW FMT) + MOVE C,T ;C <- HOP IA (DIRECT, HW FMT) + LSH C,4 + GETNET T ;T <- NET # + CAME T,[ETHUS3&NM%ETH] ;CHECK IF SAME NET # AS ME + MOVE C,[ETHGW3_4] ;C <- HOP IA (INDIRECT VIA GW, HW FMT) + PUSHJ P,ARPFND ;QUERY IA->EA MAPPING + JRST EOPKTL ;NOT FOUND, SEND ARP-REQ + JRST EOPKTK ;FOUND, BUT MAPPING NOT VALID YET + JUMPN D,EOPKT5 ;FOUND, SEND IF EA NOT 0/0 + JUMPN E,EOPKT5 + PUSHJ P,EIPFR ;FREE PKT + JRST EOPKT +;SEND A PKT FOR IP, A IS PKT, C IS HOP IA, D/E IS HOP EA0/EA1 +EOPKT5: DATAO ETH+4*1,[004270,,0] ;S0_TX_FIFOR + DATAO ETH+4*10+4*2,D ;DST EA + DATAO ETH+4*2,E + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC EA + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*2,[20000000000] ;0800 (IP) + HLRZ R,PK.BUF(A) ;R <- # OF 4-BYTE CHUNKS (>=5) + MOVN B,R ;B <- AOBJN WORD (IN 4-BYTE CHUNKS) + HRLZ B,B + HRR B,PK.BUF(A) +EOPKT6: DATAO ETH+4*10+4*2,(B) ;COPY PKT INTO FIFO + AOBJN B,EOPKT6 + PUSHJ P,EIPFR ;FREE PKT + LSH R,2 ;R <- # OF BYTES + ADDI R,12.+2. + JRST EOPKTS +] +IFE CHETHP,[ +;WE HAVE A CHAOS PKT, BUT CHETHP ISN'T TRUE. CAN'T HAPPEN. +EOPKT7: BUG HALT,[EOPKT-CHETHP] +] +IFN CHETHP,[ +;IF THE PKT IS A BRD YOU CAN'T JUST MAP IT'S DA, BUT SINCE NOBODY REALLY +;USES BRD PKTS, IT'S OK TO JUST THROW THEM AWAY (A BETTER IMPLEMENTATION MIGHT +;LOOP OVER THE ECHCA/ECHIA, AND DO THE APPROPRIATE UNICASTS) +EOPKT7: LDB T,[$CPKOP(A)] ;BRD PKT ? + CAIN T,%COBRD + JRST EOPKT9 ;YES, FLUSH +;LOOKUP THE CHAOS CA->IA->EA MAPPING USING THE ECHCA/ECHIA TABLES AND ARP + LDB T,[$CPKDA(A)] + MOVSI TT,-NECHCA +EOPKT8: CAME T,ECHCA(TT) ;SEARCH THE ECHCA TABLE + AOBJN TT,EOPKT8 + JUMPGE TT,EOPKT9 ;NOT FOUND, FLUSH + MOVE T,ECHIA(TT) ;T <- DST IA (SW FMT) + MOVE J,T ;J <- DST IA (HW FMT) + LSH J,4 + MOVE C,J ;C <- HOP IA (DIRECT, HW FMT) + GETNET T ;T <- NET # + CAME T,[ETHUS3&NM%ETH] ;CHECK IF SAME NET # AS ME + MOVE C,[ETHGW3_4] ;C <- HOP IA (INDIRECT VIA GATEWAY, HW FMT) + PUSHJ P,ARPFND ;HOP IA -> EA + JRST EOPKTL ;NOT FOUND, SEND ARP-REQ + JRST EOPKTK ;FOUND, BUT MAPPING NOT VALID YET + JUMPN D,EOPKTA ;FOUND, SEND IF EA NOT 0/0 + JUMPN E,EOPKTA +EOPKT9: PUSHJ P,ECHFR ;FREE PKT + JRST EOPKT +;SEND A PKT FOR CHAOS, A IS PKT, J IS DST IA, C IS HOP IA, D/E IS HOP EA0/EA1 +EOPKTA: DATAO ETH+4*1,[004270,,0] ;S0_TX_FIFOR + DATAO ETH+4*10+4*2,D ;DST EA + DATAO ETH+4*2,E + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC EA + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*2,[20000000000] ;0800 (IP) + LDB R,[$CPKNB(A)] ;R <- # OF BYTES OF DATA + CAILE R,%CPMXC ;MAKE SURE IT'S NOT TOO LONG + MOVEI R,%CPMXC +;BUILD 5-WORD IP HDR IN C/D/E/I/J, CHECKSUM IT, AND COPY IT INTO TX FIFO +;NOTE THAT J IS DST IA, AND SO WORD 4 OF THE IP HDR IS ALREADY IN THE RIGHT PLACE + MOVE I,[ETHUS3_4] ;WORD 3, SRC IA + MOVSI E,200100 ;WORD 2, TTL=64, CHAOS, CS=0 + MOVSI D,000001 ;WORD 1, DF=1 + MOVE C,R ;WORD 0, IPV4, 5-WORDS, LEN + ADDI C,20.+16. + LSH C,4 + TLO C,212000 + PUSHJ P,EIPCS ;COMPUTE CHECKSUM + DPB TT,[042000,,E] ;PUT CHECKSUM IN WORD 2 + DATAO ETH+4*10+4*2,C ;COPY INTO TX FIFO + DATAO ETH+4*10+4*2,D + DATAO ETH+4*10+4*2,E + DATAO ETH+4*10+4*2,I + DATAO ETH+4*10+4*2,J +;COPY CHAOS HDR (BYTE-SWAPPED) AND DATA (NORMAL, BYTE-SWAPPED) INTO TX FIFO + DATAO ETH+4*14+4*2,0(A) ;HDR, BYTE-SWAPPED + DATAO ETH+4*14+4*2,1(A) + DATAO ETH+4*14+4*2,2(A) + DATAO ETH+4*14+4*2,3(A) + MOVE B,R ;B <- AOBJN WORD, 4-BYTE WORDS + LSH B,-2 + MOVN B,B + HRLZ B,B + HRRI B,%CPKDT(A) + MOVE C,R ;C <- END, 0-3 BYTES + ANDI C,3 + PUSHJ P,CHSWAB ;WRITE DATA IN BYTE-SWAPPED MODE ? + JRST EOPKTD ;RTN+1 NO, RTN+2 YES + JUMPGE B,EOPKTC ;WRITE DATA, BYTE-SWAPPED MODE +EOPKTB: DATAO ETH+4*14+4*2,(B) + AOBJN B,EOPKTB +EOPKTC: XCT EOPKTH(C) + JRST EOPKTG +EOPKTD: JUMPGE B,EOPKTF ;WRITE DATA, NORMAL MODE +EOPKTE: DATAO ETH+4*10+4*2,(B) + AOBJN B,EOPKTE +EOPKTF: XCT EOPKTJ(C) +EOPKTG: PUSHJ P,ECHFR ;FREE PKT + ADDI R,12.+2.+20.+16. + JRST EOPKTS +;XCT EOPKTH(C) TO WRITE THE FINAL 0-3 BYTES OF DATA IN BYTE-SWAPPED MODE +EOPKTH: JFCL ;0 + DATAO ETH+4*2,(B) ;1, WRITE 2, 0XXX + DATAO ETH+4*4+4*2,(B) ;2, WRITE 2, 10XX + PUSHJ P,EOPKTI ;3, WRITE 4, 102X -> 10X2 +EOPKTI: LDB T,[141000,(B)] + DPB T,[041000,(B)] + DATAO ETH+4*14+4*2,(B) + POPJ P, +;XCT EOPKTJ(C) TO WRITE THE FINAL 0-3 BYTES OF DATA IN NORMAL MODE +EOPKTJ: JFCL ;0 + DATAO ETH+4*2,(B) ;1, WRITE 2, 0XXX + DATAO ETH+4*2,(B) ;2, WRITE 2, 01XX + DATAO ETH+4*10+4*2,(B) ;3, WRITE 4, 012X +] +;AN ARP-REQ IS ALREADY IN FLIGHT +EOPKTK: MOVEM A,EOSAV ;SAVE PKT FOR NEXT TIME WE ARE HERE + MOVEM B,EOCHS + JRST EOPKTX +;WE KNOW NOTHING ABOUT THIS IA, START GETTING AN IA->EA MAPPING +EOPKTL: MOVEM A,EOSAV ;SAVE PKT FOR NEXT TIME WE ARE HERE + MOVEM B,EOCHS + PUSHJ P,ARPADD ;MAKE AN ENTRY IN THE ARP TABLE + JRST EOPKTX ;CAN'T, TRY AGAIN LATER + DATAO ETH+4*1,[004270,,0] ;S0_TX_FIFOR + DATAO ETH+4*10+4*2,[EBCEA0] ;DST ETH ADDR (BROADCAST) + DATAO ETH+4*2,[EBCEA1] + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC ETH ADDR (ME) + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*2,[20030000000] ;0806 (ARP) + DATAO ETH+4*10+4*2,[4100000] ;0001 (ETH), 0800 (IP) + DATAO ETH+4*10+4*2,[14020000020];06 (HW LEN), 04 (SW LEN), 0001 (REQ) + DATAO ETH+4*10+4*2,[ETHEA0] ;SRC ETH/IP ADDRS (ME) + DATAO ETH+4*2,[ETHEA1] + DATAO ETH+4*10+4*2,[ETHUS3_4] + DATAO ETH+4*10+4*2,[0] ;DST ETH/IP ADDRS (IA=REMOTE, EA=0) + DATAO ETH+4*2,[0] + DATAO ETH+4*10+4*2,C + MOVEI R,12.+2.+28. ;SEND PKT +;SEND A PKT. THE DATA IS IN THE TX FIFO. THE LEN IS IN R. +EOPKTS: DATAO ETH+4*1,[004200,,0] ;S0_TX_WRSR0:S0_TX_WRSR2 <- 0:LEN + DATAO ETH+4*2,[0] + DATAO ETH+4*1,[004210,,0] + LSH R,20. + DATAO ETH+4*2,R + DATAO ETH+4*1,[004010,,0] ;S0_CR <- SEND + DATAO ETH+4*2,[000200,,0] + SETOM EOBSY ;MARK OUTPUT SIDE AS BUSY +;EVERYTHING COMES HERE TO RESTORE AND RETURN +EOPKTX: POPJ P, + +IFN CHETHP,[ +;CALLED TO PUT THE IP CHECKSUM OF C/D/E/I/J (AN IP HDR) INTO TT +;THE WORDS IN C/D/E/I/J ARE IN HW FMT, BUT ARE CONVERTED TO SW FMT BEFORE THEY GET +;ADDED INTO THE CHECKSUM, SO THAT CARRIES CAN PILE UP IN BITS 00..03 +EIPCS: MOVE TT,C ;WORD 0 + LSH TT,-4 + MOVE T,D ;WORD 1 + LSH T,-4 + ADD TT,T + MOVE T,E ;WORD 2 + LSH T,-4 + ADD TT,T + MOVE T,I ;WORD 3 + LSH T,-4 + ADD TT,T + MOVE T,J ;WORD 4 + LSH T,-4 +EIPCS0: ADD TT,T + CAIG TT,177777 ;FOLD INTO LO HALF + JRST EIPCS1 + MOVE T,TT + LSH T,-16. ;HI HALF + CARRIES + ANDI TT,177777 ;LO HALF + JRST EIPCS0 +EIPCS1: XORI TT,177777 ;FINAL 1'S COMPLEMENT + POPJ P, +]