1
0
mirror of https://github.com/PDP-10/its.git synced 2026-03-24 09:30:29 +00:00

WIP: ARP + TX implemented

This commit is contained in:
Adam Sampson
2018-08-08 22:45:04 +01:00
parent 1fc435c3eb
commit 5134ac931a
3 changed files with 354 additions and 73 deletions

View File

@@ -1,9 +1,9 @@
# Network configuration for ITS. Note: for now, the two-letter ITS
# name is hardcoded to DB, which is short for DistriBution.
HOSTNAME=DB-ITS.EXAMPLE.COM
IP=192.168.1.100
GW=192.168.0.45
NETMASK=255,255,255,248
IP=10.0.2.15
GW=10.0.2.2
NETMASK=255,255,255,0
CHAOS=no #Or octal Chaosnet address
CHAFRIENDS=chip=3150/no.nocrew.org \
chip=3143/up.update.uu.se \

View File

@@ -43,31 +43,30 @@ DEFSYM %UNVEC==120 ;Interrupt vector
DEFSYM %UNBAS==3,,774510 ;Base of Unibus register address space
DEFSYM %UNR0==%UNBAS ;PCSR0
.BEGIN %UN0
;FIXME stop using DEFSYM
DEFSYM SERI==1_15. ;status error
DEFSYM PCEI==1_14. ;port command error
DEFSYM RXI==1_13. ;receive interrupt
DEFSYM TXI==1_12. ;transmit interrupt
DEFSYM DNI==1_11. ;done interrupt
DEFSYM RCBI==1_10. ;receive buffer unavailable interrupt
DEFSYM FATL==1_9. ;fatal internal error
DEFSYM USCI==1_8. ;unsolicited state change
DEFSYM ALLINT==<SERI+PCEI+RXI+TXI+DNI+RCBI+FATL+USCI>
DEFSYM INTR==1_7. ;or of bits 15-8
DEFSYM INTE==1_6. ;interrupt enable
DEFSYM RSET==1_5. ;reset
.BEGIN %UN0 ;Bits in PCSR0
SERI==1_15. ;status error
PCEI==1_14. ;port command error
RXI==1_13. ;receive interrupt
TXI==1_12. ;transmit interrupt
DNI==1_11. ;done interrupt
RCBI==1_10. ;receive buffer unavailable interrupt
FATL==1_9. ;fatal internal error
USCI==1_8. ;unsolicited state change
ALLINT==<SERI+PCEI+RXI+TXI+DNI+RCBI+FATL+USCI>
INTR==1_7. ;or of bits 15-8
INTE==1_6. ;interrupt enable
RSET==1_5. ;reset
.END %UN0
.BEGIN %UNCMD
DEFSYM NOP==0
DEFSYM GETPCB==1
DEFSYM GETCMD==2
DEFSYM SLFTST==3
DEFSYM START==4
DEFSYM BOOT==5
DEFSYM PDMD==10 ;polling demand
DEFSYM HALT==16
DEFSYM STOP==17
.BEGIN %UNCMD ;Command field in PCSR0
NOP==0
GETPCB==1
GETCMD==2
SLFTST==3
START==4
BOOT==5
PDMD==10 ;polling demand
HALT==16
STOP==17
.END %UNCMD
DEFSYM %UNR1==%UNBAS+2 ;PCSR1
@@ -76,33 +75,36 @@ DEFSYM %UNR2==%UNBAS+4 ;PCSR2
DEFSYM %UNR3==%UNBAS+6 ;PCSR3
.BEGIN %UNAF ;ancillary function codes in PCB
DEFSYM NOP==0
DEFSYM START==1 ;start microcode at
DEFSYM RDDPA==2 ;read default physical address
DEFSYM RDPA==4 ;read physical address
DEFSYM WRPA==5 ;write "
DEFSYM RDMAL==6 ;read multicast address list
DEFSYM WRMAL==7 ;write "
DEFSYM RDDRF==10 ;read descriptor ring format
DEFSYM WRDRF==11 ;write "
DEFSYM RDCTRS==12 ;read counters
DEFSYM RCCTRS==13 ;read and clear counters
DEFSYM RDMODE==14 ;read mode register
DEFSYM WRMODE==15 ;write "
DEFSYM RDSTAT==16 ;read status
DEFSYM RCSTAT==17 ;read and clear status
DEFSYM RDMEM==20 ;read internal memory
DEFSYM WRMEM==21 ;write "
DEFSYM RDSID==22 ;read system ID parameters
DEFSYM WRSID==23 ;write "
DEFSYM RDLSA==24 ;read load server address
DEFSYM WRLSA==25 ;write "
.BEGIN %UNAF ;Ancillary function codes in PCB
NOP==0
START==1 ;start microcode at
RDDPA==2 ;read default physical address
RDPA==4 ;read physical address
WRPA==5 ;write "
RDMAL==6 ;read multicast address list
WRMAL==7 ;write "
RDDRF==10 ;read descriptor ring format
WRDRF==11 ;write "
RDCTRS==12 ;read counters
RCCTRS==13 ;read and clear counters
RDMODE==14 ;read mode register
WRMODE==15 ;write "
RDSTAT==16 ;read status
RCSTAT==17 ;read and clear status
RDMEM==20 ;read internal memory
WRMEM==21 ;write "
RDSID==22 ;read system ID parameters
WRSID==23 ;write "
RDLSA==24 ;read load server address
WRLSA==25 ;write "
.END %UNAF
.BEGIN %UNTD ;bits in transmit/receive descriptors
DEFSYM OWN==<1_15.>
DEFSYM ERRS==<1_14.>
.BEGIN %UNTD ;Bits in transmit/receive descriptors
OWN==<1_15.>
ERRS==<1_14.>
OFLO==<1_13.>
STF==<1_9.>
ENF==<1_8.>
.END %UNTD
;Layout of memory shared with DEUNA.
@@ -129,7 +131,7 @@ IFG %UNRDR+<%UNNRB*8>-<1000*4>, .ERR DEUNA first half-page full
;buffers.
DEFSYM %UNNPG==1+<%UNNTB/2>+<%UNNRB/2>
DEFSYM %UNBSZ==2048.
DEFSYM %UNBOF==2 ;Padding at start, so the packet
;data starts on a PDP-10 word
DEFSYM %UNBOF==2 ;Padding at start, so the packet
;data starts on a PDP-10 word
IFN $$TEMP,EXPUNG DEFSYM

View File

@@ -15,8 +15,226 @@
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Generic Ethernet support
%NE32==37777777777
%NE16==177777
%NE8==377
.BEGIN %NEH ;Fields in the Ethernet header
LENGTH==<2+6+6+2>
WORDS==<LENGTH/4>
PAD==<.BP <%NE16_20.>,0>
;FIXME Would all the MAC stuff be easier if this was 3 16-bit fields?
DMAC0==<.BP <%NE16_4>,0>
DMAC12==<.BP <%NE32_4>,1>
SMAC01==<.BP <%NE32_4>,2>
SMAC2==<.BP <%NE16_20.>,3>
TYPE==<.BP <%NE16_4>,3> ;see %NETYP
.END %NEH
.BEGIN %NETYP ;Ethernet frame types
IP==4000
ARP==4006
.END %NETYP
.BEGIN %NEAH ;Fields in an Ethernet+IPv4 ARP packet
LENGTH==<2+2+1+1+2+6+4+6+4> ;should be this long
WORDS==<<LENGTH+3>/4>
HRD==<.BP <%NE16_20.>,0> ;see %NEAHR
PRO==<.BP <%NE16_4>,0> ;see %NETYP
HLN==<.BP <%NE8_28.>,1> ;must be 6 for Ethernet MAC
PLN==<.BP <%NE8_20.>,1> ;must be 4 for IPv4 address
OP==<.BP <%NE16_4>,1> ;see %NEAOP
SHA01==<.BP <%NE32_4>,2>
SHA2==<.BP <%NE16_20.>,3>
SPA0==<.BP <%NE16_4>,3> ;SPA split across words
SPA1==<.BP <%NE16_20.>,4>
THA0==<.BP <%NE16_4>,4>
THA12==<.BP <%NE32_4>,5>
TPA==<.BP <%NE32_4>,6>
.END %NEAH
.BEGIN %NEAHR ;ARP hardware type
ETHER==1
.END %NEAHR
.BEGIN %NEAOP ;ARP operation
REQ==1
REPLY==2
.END %NEAOP
%NEATS==64. ;Max number of ARP table entries
.BEGIN %NEAT ;ARP table entry
WORDS==3
HA01==<.BP <%NE32>,0> ;MAC address
HA2==<.BP <%NE16>,1>
PA==<.BP <%NE32>,2> ;IPv4 address
.END %NEAT
EBLK
ETHME: BLOCK %NEAT"WORDS ;Our MAC address, as ARP table entry
;(device driver must initialise this)
ETHHBF: BLOCK %NEH"WORDS ;Ethernet header unpacked
ETHABF: BLOCK %NEAH"WORDS ;ARP packet unpacked
ETHAT: BLOCK <%NEATS*%NEAT"WORDS> ;ARP table
ETHATS: 0 ;Number of entries in ARP table
BBLK
;Process a received packet.
;R is buffer. Length in bytes is I. May clobber A-I, R.
;
ETHRX: MOVEI TT,ETHHBF ;Unpack Ethernet header into ETHHBF
HRL TT,R
BLTUB TT,<ETHHBF+%NEH"WORDS-1>
SUBI I,%NEH"LENGTH ;I now contains data length
ADDI R,%NEH"WORDS ;R points to data
LDB A,[%NEH"TYPE+ETHHBF]
BUG INFO,[etype=],OCT,A
CAIN A,%NETYP"IP
JRST ETHRXI
CAIN A,%NETYP"ARP
JRST ETHRXA
BUG INFO,[Unknown Ethernet type],OCT,A
POPJ P,
;Process an ARP packet.
;
ETHRXA: CAIN I,%NEAH"LENGTH ;Check size first
JRST ETHRAS
MOVEI TT,ETHABF ;Unpack packet into ETHABF
HRL TT,R
BLTUB TT,<ETHABF+%NEAH"WORDS-1>
LDB A,[%NEAH"HRD+ETHABF]
LDB B,[%NEAH"HLN+ETHABF]
HRL B,A
CAME B,[%NEAHR"ETHER,,6]
JRST ETHRAH
LDB A,[%NEAH"PRO+ETHABF]
LDB B,[%NEAH"PLN+ETHABF]
HRL B,A
CAME B,[%NETYP"IP,,4]
JRST ETHRAP
LDB A,[%NEAH"SPA0+ETHABF] ;Get source IP address
LSH A,16.
LDB B,[%NEAH"SPA1+ETHABF]
IOR A,B
BUG INFO,[ARP source addr ],OCT,A
MOVE E,ETHATS ;Is the IP address in the table already?
SOS E
ETHRX1: JUMPL E,ETHRX2 ;Any more entries to check?
LDB B,[%NEAT"PA+ETHAT(E)]
BUG INFO,[ARP table entry ],OCT,E,[ of ],OCT,ETHATS,[ is ],OCT,B
CAMN A,B ;Match?
JRST ETHRX3 ; Yes - update it
SOJA E,ETHRX1 ;Prev entry
ETHRX2: MOVE E,ETHATS ;Not found in table - add new entry
CAIL E,%NEATS ;Table full?
JRST [ MOVEI E,1 ; Yes - flush it and start over
MOVEM E,ETHATS ; FIXME remove a random entry instead
SETZM E
JRST ETHRX3]
AOS ETHATS
ETHRX3: DPB A,[%NEAT"PA+ETHAT(E)] ;Store IP address
LDB C,[%NEAH"SHA01+ETHABF] ;Get sender's MAC
LDB D,[%NEAH"SHA2+ETHABF]
DPB C,[%NEAT"HA01+ETHAT(E)] ;Store MAC
DPB D,[%NEAT"HA2+ETHAT(E)]
BUG INFO,[Set ARP table entry ],OCT,E,[ to ip ],OCT,A,[ mac ],OCT,C,[ ],OCT,D
LDB E,[%NEAH"OP+ETHABF] ;Get op
BUG INFO,[ARP op ],OCT,E
CAIE E,%NEAOP"REQ ;Is this a request?
POPJ P, ;No - nothing more to do
LDB B,[%NEAH"TPA+ETHABF] ;Get the target PA
CAME B,[ETHUS] ;Is it our address?
POPJ P, ;No - nothing more to do
BUG INFO,[ARP reply]
MOVEI E,%NEAOP"REPLY ;Construct reply packet
DPB E,[%NEAH"OP+ETHABF]
DPB A,[%NEAH"TPA+ETHABF] ;Set sender PA as target PA
DPB B,[%NEAH"SPA1+ETHABF] ;Set our PA as source PA
LSH B,-16.
DPB B,[%NEAH"SPA0+ETHABF]
MOVE E,C ;Reshuffle sender's MAC from 01/2 to 0/12 form
LSH C,-16.
LSH E,16.
IOR D,E
DPB C,[%NEAH"THA0+ETHABF] ;Set as target HA
DPB D,[%NEAH"THA12+ETHABF]
DPB C,[%NEH"DMAC0+ETHHBF] ;Set as destination MAC in header
DPB D,[%NEH"DMAC12+ETHHBF]
LDB C,[%NEAT"HA01+ETHME] ;Get our HA
LDB D,[%NEAT"HA2+ETHME]
DPB C,[%NEAH"SHA01+ETHABF] ;Set as source HA
DPB D,[%NEAH"SHA2+ETHABF]
MOVEI R,ETHABF ;Send it!
MOVEI I,%NEAH"LENGTH
JRST ETHTX
ETHRAS: BUG INFO,[ARP wrong size packet ],OCT,I
POPJ P,
ETHRAH: BUG INFO,[ARP wrong hardware type ],OCT,B
POPJ P,
ETHRAP: BUG INFO,[ARP wrong protocol ],OCT,B
POPJ P,
;Process an IPv4 packet.
;
ETHRXI:
BUG INFO,[IP]
POPJ P,
;Send an Ethernet packet (if possible).
;Unpacked header is in ETHHBF. R contains pointer to unpacked data.
;I contains data length in bytes.
;
;FIXME IFN UNAP,...
ETHTX: BUG INFO,[ethtx ptr ],OCT,R,[ len ],OCT,I
PUSHJ P,UNAFF ;Find a free transmit buffer
POPJ P, ;None left. Give up.
BUG INFO,[ethtx buf ],OCT,B,[ desc ],OCT,D,[ len ],OCT,I
MOVE TT,B ;Convert header
HRLI TT,ETHHBF
BLTBU TT,<%NEH"WORDS-1>(B)
ADDI B,%NEH"WORDS ;Convert data
MOVE TT,B
HRL TT,R
MOVE A,I
ADDI A,3
IDIVI A,4
ADD A,B
MOVE C,TT
BUG INFO,[ethtx bltbu tt ],OCT,C,[ a ],OCT,A
BLTBU TT,(A)
ADDI I,%NEH"LENGTH ;Add length of header
BUG INFO,[ethtx end buf ],OCT,B,[ desc ],OCT,D,[ len ],OCT,I
JRST UNATX ;Transmit it
;Check whether the interface is able to send a packet.
;Skip-return if it is.
;
ETHCTS:
;FIXME check if we have an ARP entry, and if not, send a request
AOS (P)
@@ -36,6 +254,7 @@ EBLK
;that allocated and mapped a page, returning the PDP-10
;address and the two Unibus addresses. We could then
;allocate on the fly while setting up the rings.
;FIXME The setup stuff might also be cleaner with byte ptrs as above.
UNPAGS: BLOCK %UNNPG ;PDP-10 pages: 0,,addr
UNPAGU: BLOCK %UNNPG ;Unibus pages: first-addr,,second-addr
@@ -129,15 +348,26 @@ UNAIN1: PUSHJ P,TCALL ;Allocate a page of unshuffleable low core
MOVEI A,%UN0"DNI+%UNCMD"GETPCB ;Ack DNI as it's on after reset
PUSHJ P,UNACMD ;We've really returned to the caller here
IFN 1,[
;Read, and display, the MAC address
;Get the MAC address for ARP to use
MOVE A,UNPAGS
MOVSI TT,%UNAF"RDDPA
MOVEM TT,0(A)
MOVEI A,%UNCMD"GETCMD
PUSHJ P,UNACMD
PUSHJ P,UNDPCB ;Show results
]
MOVEI TT,ETHHBF ;Unpack MAC address into ETHHBF
HRL TT,UNPAGS
BLTUB TT,ETHHBF+1
MOVE TT,[.BP <%NE16_4.>,ETHHBF]
LDB A,TT
LSH A,16.
ILDB B,TT
IOR A,B
BUG INFO,[my MAC 01 =],OCT,A
DPB A,[%NEAT"HA01+ETHME]
ILDB A,TT
BUG INFO,[my MAC 2 =],OCT,A
DPB A,[%NEAT"HA2+ETHME]
;Set up transmit and receive rings
MOVE D,UNPAGS ;Point to TDR (RDR follows)
@@ -151,7 +381,7 @@ UNAIN2: MOVE TT,C ;Work out index into UNPAGS/UNPAGU
HLRZ B,UNPAGU(TT) ;Get Unibus addr. Even on the left...
TRNE C,1
HRRZ B,UNPAGU(TT) ;... and odd on the right
ADDI B,%UNBOF ;Add padding at start
ADDI B,%UNBOF ;Add word-aligning padding at start
;FIXME This bit for now, until I rewrite this whole section..
HRLM D,UNTXRP(C) ;Descriptor pointer
@@ -257,7 +487,7 @@ UNABRK: 0
JSR UTCSAV
IORDI H,%UNR0 ;Read status
BUG INFO,[DEUNA interrupt, PCSR0=],OCT,H,[ UNADNI=],OCT,UNADNI
;BUG INFO,[DEUNA interrupt, PCSR0=],OCT,H,[ UNADNI=],OCT,UNADNI
TRNE H,%UN0"SERI+%UN0"PCEI+%UN0"FATL+%UN0"USCI
BUG HALT,[DEUNA error, PCSR0=],OCT,H ;FIXME do something better!
@@ -287,44 +517,93 @@ UNABRK: 0
;
UNARX: MOVSI W,<-%UNNRB> ;W = -Number to check,,buffer index
HRR W,UNRXRI
SETOM UNRXRI ;Haven't found an empty slot yet
SETOM UNRXRI ;Haven't found an empty buffer yet
UNARX1: HRRZ A,W ;Wrap index around
CAIL A,%UNNRB
HLLZS W
HLRZ J,UNRXRP(W) ;Descriptor
HRRZ R,UNRXRP(W) ;Buffer
MOVE Q,1(J) ;Is there a packet in this slot? (OWN=0)
BUG INFO,[check rx slot],OCT,W,[desc],OCT,J,[buf],OCT,R,[flags],OCT,Q
MOVE Q,1(J) ;Is there a packet in this buffer? (OWN=0)
TLNE Q,%UNTD"OWN
JRST [ SKIPGE UNRXRI ;No. First empty slot we've found?
JRST [ SKIPGE UNRXRI ;No. First empty buffer we've found?
HRRZM W,UNRXRI ; Yes, start here next time
JRST UNARX2]
MOVE A,0(R)
MOVE B,1(R)
MOVE C,2(R)
BUG INFO,[got packet],OCT,W,[data],OCT,A,[ ],OCT,B,[ ],OCT,C
TLNE Q,%UNTD"STF ;STF+ENF should always be true, but check...
TLNN Q,%UNTD"ENF
JRST UNARSF
;FIXME process
TLNE Q,%UNTD"ERRS+%UNTD"OFLO
JRST UNARER
TLO Q,%UNTD"OWN ;Set OWN=1 to mark as free
HRRZ R,UNRXRP(W) ;Buffer
LDB I,[.BP 7777,1(J)] ;Get MLEN
PUSHJ P,ETHRX
UNARX3: TLO Q,%UNTD"OWN ;Set OWN=1 to mark as free
MOVEM Q,1(J)
SKIPE UNARCB ;Have we had an RCB interrupt?
JRST [ SETZM UNARCB ;Yes. Tell the DEUNA there's a free slot now.
JRST [ SETZM UNARCB ;Yes. Tell the DEUNA there's a free buffer now.
MOVEI A,%UN0"INTE+%UNCMD"PDMD
IOWRI A,%UNR0
JRST UNARX2]
UNARX2: AOBJN W,UNARX1 ;Repeat if we haven't looked at all slots
SKIPGE UNRXRI ;Repeat if we haven't found a free slot
UNARX2: AOBJN W,UNARX1 ;Repeat if we haven't looked at all buffers
SKIPGE UNRXRI ;Repeat if we haven't found a free buffer
JRST UNARX1 ; FIXME: Or maybe HRRZM W,UNRXRI ?
POPJ P,
;These are only here because you can't use BUG inside []...
UNARSF: BUG INFO,[DEUNA split frame ],OCT,Q
JRST UNARX3
UNARER: BUG INFO,[DEUNA frame with errors ],OCT,Q
JRST UNARX3
;Find an empty buffer in the transmit ring.
;On success, skip return with descriptor in D, buffer in B.
;On failure (the ring is full), normal return.
;Clobbers A-TT.
;
UNAFF: MOVSI E,<-%UNNTB> ;E = -Number to check,,buffer index
HRR E,UNTXRI
UNAFF1: HRRZ A,E ;Wrap index around
CAIL A,%UNNTB
HLLZS E
HLRZ D,UNTXRP(E) ;Descriptor
MOVE A,1(D) ;Is this buffer free? (OWN=0)
BUG INFO,[unaff checking slot ],OCT,E,[ status ],OCT,A
TLNE A,%UNTD"OWN
JRST [ AOBJN E,UNAFF1 ;Try the next one
POPJ P,] ;No buffers free.
HRRZM E,UNTXRI ;Yes. Start at this buffer + 1 next time.
AOS UNTXRI ; (Doesn't matter if it wraps.)
HRRZ B,UNTXRP(E) ;Buffer
BUG INFO,[unaff found free buffer ],OCT,E,[ desc ],OCT,D,[ buff ],OCT,B
AOS (P) ;Skip return
POPJ P,
;Transmit a packet from a buffer obtained by UNAFF.
;Descriptor in D, buffer in B, data length in bytes in I.
;Clobbers A.
;
UNATX: BUG INFO,[unatx desc ],OCT,D,[ buff ],OCT,B,[ length ],OCT,I
HRLM I,0(D) ;Set SLEN
MOVSI A,%UNTD"OWN+%UNTD"STF+%UNTD"ENF
IORM A,1(D) ;Set flags
MOVEI A,%UN0"INTE+%UNCMD"PDMD ;Tell the DEUNA to check the ring
IOWRI A,%UNR0
POPJ P,
;FIXME
;Stylewise, trying to match IMP...
;See: