Ethernet II feasibility on the ND Ethernet II card - the 0x1888A mode word decoded (2026-07-25)¶
Date: 2026-07-25
Subsystem: ND Ethernet II (PCB 3094 / ND-110063), ENCOS MC68000 firmware
Binary: ..\..\..\..\Installation\Communication\Ethernet\x\stripped\encos-ser-all-banks-68k.bin
(68000 big-endian, base 0x0; the active Ghidra program)
Question this answers: can this card carry ordinary TCP/IP (Ethernet II / DIX) traffic, and can it do so while COSMOS keeps running?
Convention (same as ETHII-HOST-PROTOCOL-SPEC-2026-07-25.md): [V] = verified from the firmware disassembly, Ghidra address cited. [U] = unverified / inferred, flagged for a live trace before relying on it.
CORRECTION (2026-07-26) - THE TL;DR BELOW IS SUPERSEDED. READ THIS FIRST.¶
The firmware-level analysis in this document is correct and stands. The system-level conclusion was wrong, because this document analysed only the LNMA firmware layer (0x5000-0x7000) and missed the ENCOS server that runs above it on the same 68000.
Newly verified [V]: - The COSMOS frame is built on the card, by the ENCOS server at
0x83E6-0x849C- NOT by the ND-100. It writeshdrLen = 14,totalLen, and starts its LLC payload (a8 a8 03 0b 02) atbase+14(stores at 0x845E / 0x8464 / 0x847E / 0x8482 / 0x8488). Wire bytes 12-13 are written by nobody but the firmware at 0x60AA. - The on-card RX classifier at0xA18Ecomputes payload asbase + hdrLenand then tests(A3)==0xA8,(1,A3)==0xA8,(2,A3)==0x03. Withg_mode8023LengthField = 0the firmware reportshdrLen = 12, so the server reads the LENGTH FIELD as DSAP/SSAP and rejects every COSMOS frame. - The server hard-codes +-14 header arithmetic elsewhere too (0x8E50,0xADD4).Therefore setting
g_mode8023LengthField = 0breaks COSMOS in BOTH directions, not just transmit (section 8 below says receive survives - that is WRONG, it only survives the firmware gate, then dies at the server's LLC check).And it cannot be fixed from the ND-100. The ND-100 never sees a MAC frame: the card is an XMSG client of the ND-100 kernel over the PIOC XMSG box + SUPERKICK ring (PIOC word
1012B, pattern52525B/125252B), consumed byPDRIVin..\..\..\NPL-SOURCE\NPL\MP-P2-PIOC-DRIV.NPL. No ND-100 image contains the mode-word address142105Bor the ready-list address142153B. The list at 0x188D6 is drained by FIRMWARE code (0x6E7C / 0x6E96), so "the host receives the complete frame" in section 4 means the on-card server, not the ND-100.Revised verdict: Ethernet II is supported by the low-level firmware but blocked by the on-card ENCOS server. A dual-stack machine needs either a patched ENCOS server or a card dedicated to one mode. The one ND-100-side route that bypasses the server entirely is MON 255 EXEL
LDATX/STATXagainst card DRAM - viable for control, but it moves one word per monitor call and so cannot carry 1514-byte frames at any useful rate.CONFIRMED BY ND'S OWN DOCUMENTATION (2026-07-26)¶
Norsk Data shipped exactly this: COSMOS TCP/IP Gateway for Ethernet, product 211185, which runs on the same ND 110063 Ethernet II card and whose documented Data Link standard is "Baseband Ethernet: DIX 2.0" with ARP (RFC 826) - impossible under the ENCOS LLC path. It works by loading a different 68000 image into the card at cold start.
ND's own hardware manual for this card (
..\..\..\..\Reference-Manuals\Devices\ND-12.055.1 EN Ethernet II Controller.md, Appendix C) tabulates the COSMOS stack asLLC1 / MACat layer 2 and the ARPA stack asLLC1 / DIX, with the footnote "to be implemented late 1987 by Ethernet II". So the framing split this document derived from the firmware is documented by ND.Full documentary evidence, product family, layer split (TCP on ND-100, IP on the controller), the per-protocol image mechanism, and the coexistence question: HOW-ND-SHIPPED-TCPIP-PRODUCT-EVIDENCE-2026-07-26.md
SECOND RE PASS (2026-07-26) - THE FOUR-ADDRESS SCHEME, THE LANCE, AND BROADCAST¶
Two independent Ghidra passes (software-side and hardware-side) settled three things.
A. The four-address multi-protocol scheme is NOT implemented on this card - VERDICT: NO [V]¶
ND-60.197.01 Ethernet Basic Software Programmer Guide, document page 11 section 2.4, describes a scheme where "each Ethernet Interface has in fact four physical addresses ... to make it possible to support multiple link level protocols simultaneously, using the same hardware", with bits 7-6 of MAC byte 5 selecting
00IEEE /01DIX /10user-written /11ND (COSMOS Ethernet Option). Imported at..\..\..\..\Reference-Manuals\ND-60.197.01 EN Ethernet Basic Software Programmer Guide.md.That manual describes the earlier TWO-BOARD Ethernet I Interface. The scheme did not survive into the one-board ND 110063. Evidence, from both directions:
Software side: -
0x5D7Eunicast compare is an exact six-byte equality loop (moveq #5,D2 / move.b (A0)+,D3 / move.b (A1)+,D4 / cmp.b D4,D3 / bne / dbf), raw bytes16 18 18 19 b6 04 66 06 51 ca ff f6. Noandi, no shift, nobtst, neither operand pre-masked. -0x545Agroup-filter compare is the same exact six-byte loop. - Image-widesearch_bytes: 0 hits forandi.b #$C0,#$3F,#$BF,#$7F,#$FC; 0 hits forand.b #$C0/#$3F,Dn; 0 hits forcmpi.b #$C0; and 0 hits forbtst #6anywhere in the image. The literal OUI08 00 26appears only as instruction bytes - it is not a constant. - The only MAC bit ever masked is the I/G bit (and.b #1at 0x5D64, 0x688A, 0x6980). - Nothing addresses byte 5 in isolation - no xrefs to 0x18863 at all. - There is no protocol-family concept anywhere. The only demultiplex is a single hardcoded 802.2 SAP triple at0xA1A4:DSAP==0xA8,SSAP==0xA8,control==0x03.Hardware side: -
INITLANCE@ 0x48EA programs exactly ONE physical address, MODE = 0x0000, LADRF = 0. -LNNDTOMAAPPEND@ 0xF05A builds the station MAC as08:00:26:<sysno lo>:<sysno hi>:and thenclr.bbyte 5 at0xF0A2- a hard constant zero, i.e. the manual's IEEE family. The firmware never writes 0x40, 0x80 or 0xC0 there. Peer addresses built at 0xB056/0xB156 use the same routine. - PADR is copied verbatim fromg_stationMacAddress, six bytes, unmasked (0x4970-0x49DA).Consequence: on the Ethernet II card, protocol families are separated by 802.2 SAP, not by address bits. This independently corroborates the "one protocol per card, one downloaded image at a time" conclusion.
B. Broadcast CAN reach the card - open question O1 is RESOLVED [V]¶
MODE =
0x0000, so PROM is clear but DRCVBC (disable-receive-broadcast, bit 14) is never written either - only bits 15, 6, 5, 4, 3, 2, 1, 0 are ever touched. The Am7990 always acceptsFF:FF:FF:FF:FF:FFregardless of LADRF (LADRF gates multicast only). So ARP and other broadcast frames ARE delivered by the hardware to the firmware. Whether they survive is then purely the software question already answered in section 5: the group filter at 0x542C has no broadcast case, so a broadcast is kept only ifFF:FF:FF:FF:FF:FFis registered in the group list, or ifg_addressFilterEnableis 0.Note the hardware honours that flag too: at
0x48F8-0x4912,g_addressFilterEnable == 0causesori.w #0x8000into MODE, i.e. it sets LANCE PROM. The promiscuous semantics recorded in this document are implemented at the silicon level as well as in software.C. LANCE facts recovered [V]¶
- Registers:
0xEF00A2= RAP,0xEF00A0= RDP (proven byINTLANCE@ 0x47F8 reading CSR0 and writing it back to clear, then testing ERR/MISS/BABL|MERR/RINT|TINT).- Init block
LANCEINITB@ DRAM 0x18810: MODE +0, PADR +2, LADRF +8, RDRA +0x10, TDRA +0x14. Built byINITLANCE@ 0x48EA.- CSR sequence: CSR3 = 0x0004 (BSWP), CSR1 = 0x8810, CSR2 = 0x0001 (block at 0x018810), CSR0 = INIT, then
0x0042(INEA|STRT) at 0x4890; stop writes0x0004at 0x48C8.- Ring lengths:
ori.w #0xE000at 0x4A94 / 0x4AB8 -> RLEN = TLEN = 7 -> 128 descriptors each, matching the 0x18000 / 0x18408 anchors.- LADRF is zero-initialised then filled by a CRC hash (0x4754 -> 0x1342C / 0x1310C) over a runtime list of subscribed group addresses at
0x18942(subscribe 0x53AC, unsubscribe 0x53EC). With nothing subscribed LADRF = 0 and all multicast is rejected.0x503Ais not the LANCE programmer - it starts two PIOC-OS objects,LNMASPCOMM(0x18834) andLNMASPDATA(0x18848), via 0x1179C (magic0xAAAFcheck).D. CORRECTION -
0x18886is the LANCE loopback-mode selector [V]¶This document (and the Ghidra database) previously named
0x18886g_txMinLengthPadMode. That name was too narrow.INITLANCEat0x492Aswitches on it through a case table at0x18954([0]=0x495E [1]=0x493E [2]=0x495E [3]=0x494E [4]=0x495E), where 0x493E sets LOOP+INTL (internal loopback), 0x494E sets LOOP (external loopback) and 0x495E clears both (normal operation). The value 4 written at init therefore means normal, non-loopback operation.The TX-pad reading is a genuine second consumer and is compatible:
XMTRINGAPPENDat0x6110doescmpi.w #4,(0x18886)and pads short frames to 60 bytes only when it equals 4 - i.e. padding is applied only in normal mode. Both consumers must be kept in mind; everywhere this document says "keepword[0x14] = 4", read it as "keep the card in normal, non-loopback mode".E. The firmware carries its own symbol table [V]¶
A vendor symbol table sits at approximately file offset 0x66D00, records of the form
flags | addr | 12-char name. It is the source of the namesINITLANCE,INTLANCE,STARTIO,LANCEINITB,LNMAPHYSICALADDRESS,LNMASPCOMM. Mining it wholesale is the single highest-value action available on this binary and is in progress.F. Unresolved conflict¶
One agent reports
0x83E6/0x83E8is a buffer-array init (walking a table at 0x1CF32, entry size 0x60); an earlier pass placed the COSMOS TX frame build at 0x83E6-0x849C and quoted decoded bytes for it (847E: 14 bc 00 a8=move.b #0xa8,(A2)). Both may be parts of one function, or one is wrong. The claim in the first correction banner above that the frame build lives at 0x83E6 rests on this and is not yet settled - a clean disassembly of 0x83E6-0x84A0 is needed.
TL;DR¶
Ethernet II is already supported by the firmware. It is not enabled by default, and it is turned on purely by host configuration - no firmware patch is needed. [V]
The word at DRAM 0x1888A (now named g_mode8023LengthField in the Ghidra database) is not an
"802.3 vs Ethernet II" selector. It is a "is there a length field in the header" switch:
| Value | Receive | Transmit |
|---|---|---|
!= 0 (power-on default 1) |
14-byte header; frames 61..1514 accepted only if bytes 12-13 == payload length | firmware writes the length into bytes 12-13 |
== 0 |
14-byte check skipped entirely; every in-range frame passes | firmware writes only dst+src (12 bytes); host owns bytes 12-13 |
With the mode word cleared the card becomes a raw frame pass-through in both directions, which is exactly what a host-side TCP/IP stack needs. Ethernet II frames are dropped in the default mode only as a side effect of the length-equality test - an EtherType is >= 0x0600 (1536) and the payload is <= 1500, so the equality can never hold.
The firmware contains no EtherType logic whatsoever [V]: no 1536/0x0600 threshold, no
0x0800/0x0806/0x86DD constants used in frame parsing, no LLC DSAP/SSAP decode, no SNAP decode, no
protocol table. 86 dd does not occur anywhere in the image; the only 08 06 byte match in the whole
binary is the instruction btst.l #0xe,D6 at 0x5CC8.
1. The mode word - complete cross-reference¶
g_mode8023LengthField, word, DRAM 0x1888A, card BSS, word aligned. Seven cross-references, all
absolute .l addressing - there are no indirect/pointer references, so the full set is known. [V]
| Address | Dir | Site | Effect |
|---|---|---|---|
0x7026 |
W | LNMAINIT power-on init | = 1 (802.3 length mode ON by default) |
0x679A |
W | SET-MODE-FLAGS command handler | = command node word[0x18], unvalidated |
0x5D0A |
R | RCVCOMPLETE classifier | zero -> skip the length check entirely |
0x5E7C |
R | RCVCOMPLETE delivery-node build | selects hdrlen 14 vs 12 reported to the host |
0x6086 |
R | XMTRINGAPPEND header build | selects whether a length word is written |
0x6BB6 |
R | TX command validation | requires hdrlen >= 14 |
0x6BCC |
R | TX command validation | requires hdrlen >= 12 |
2. Receive classification - the actual algorithm [V]¶
Reconstructed instruction-by-instruction from RCVCOMPLETE @ 0x5C42:
if (RMD1 & OWN) yield(); // 0x5C72
if (BCNT == 0) yield(); // 0x5C80
frameLen = (MCNT & 0x0FFF) - 4; // 0x5CA2 (FCS stripped)
if (RMD1 & ERR) hardwareErrorDrop(); // 0x5CC8
/* size gate - runs BEFORE the mode word is consulted */
if (frameLen < 60 || frameLen > 1514) { // 0x5CD0 / 0x5CDA, both UNSIGNED
formatOk = 0; stats[0x2A]++; // runt / oversize counter
}
else if (g_mode8023LengthField == 0) { // 0x5D0A
formatOk = 1; // RAW MODE: no check at all
}
else if (frameLen <= 60) { // 0x5D14, UNSIGNED
formatOk = 1; // BYPASS: short frames unchecked
}
else {
formatOk = (be16(frame + 12) == frameLen - 14); // 0x5D1C / 0x5D20
if (!formatOk) stats[0x24]++; // length-mismatch counter
}
/* address check */
if (frame[0] & 1) addrOk = GroupAddressFilterMatch(frame); // 0x5DCC
else addrOk = (memcmp(frame, g_stationMacAddress, 6) == 0); // 0x5D7E
if (!addrOk && g_addressFilterEnable == 0) addrOk = 1; // 0x5D8C / 0x5DDE
if (!addrOk) discard(); // GATE 1, 0x5DF2
if (!formatOk) discard(); // GATE 2, 0x5DFA
if (rxPoolEmpty()) discard(); // GATE 3, 0x5E02 / 0x5E0E
deliverZeroCopy(); // 0x5E1C
Signed-vs-unsigned: every magnitude comparison in this path is BCS/BCC (unsigned) or a plain
equality/BNE. There is no signed-comparison hazard anywhere in the classifier. [V]
Byte order: the length/type field is read with a single big-endian move.w (0xc,A4),D1w at
0x5D1C. No DMA byte-swap, no word-swap, no byte-wise reassembly. [V]
Handling of the reserved gap 1501..1535: in mode != 0 such a value can never equal a payload
length (payload <= 1500), so those frames are rejected by the same equality test as any DIX frame. In
mode == 0 they are accepted and passed through uninterpreted. The firmware has no explicit
handling of the gap - it simply falls out of the equality test. [V]
Which model does this match¶
Not Model A (proper length/type discrimination). The receive path is Model B in the default mode (field interpreted exclusively as a length) and Model D in mode 0 (raw frame forwarding, host interprets the field). There is no Model C (no LLC inspection) and no Model E (no hardware protocol classification is read from the descriptor - only OWN/ERR/CRC/FRAM/OFLO/BUFF). [V]
3. Transmit path [V]¶
XMTRINGAPPEND @ 0x6054:
if (g_mode8023LengthField) { // 0x6086
hdr = base + hdrLen - 14;
be16(hdr + 12) = totalLen; // 0x60AA - firmware WRITES an 802.3 length field
wireLen = 14 + totalLen;
} else { // 0x60BC
hdr = base + hdrLen - 12;
/* nothing is written at hdr+12 - the host's first two payload bytes land there */
wireLen = 12 + totalLen;
}
memcpy(hdr + 0, cmdNode + 0x22, 6); // 0x60E0 - dst MAC supplied by the HOST
memcpy(hdr + 6, g_stationMacAddress, 6); // 0x60EE - src MAC supplied by the FIRMWARE
if (g_txMinLengthPadMode == 4 && wireLen < 60) wireLen = 60; // 0x6110
Validation before this, at 0x6BB6 / 0x6BCC / 0x6BEC:
| Check | Mode != 0 | Mode == 0 | Error |
|---|---|---|---|
| descriptor.hdrLen | >= 14 | >= 12 | -0x17 |
| descriptor.totalLen | <= 1500 (0x5DC) | <= 1500 | -0x16 |
So in mode 0 the host can place any 16-bit value at wire bytes 12-13, including 0x0800, 0x0806 and 0x86DD, simply by making it the first two bytes of its payload buffer. The firmware never inspects, validates or rewrites it. 1500 is used only as an MTU bound; 1536 / 0x0600 appears nowhere in the image. [V]
4. What the host actually receives - raw pass-through proof [V]¶
In the accept path at 0x5E72:
descriptor.base(delivery node + 0x18) = the LANCE buffer address = byte 0 of the frame, i.e. the destination MAC. The frame is not copied and the MAC header is not stripped - delivery is zero-copy.descriptor.len(node + 0x1C) = the buffer size derived from-BCNT, not the frame length.descriptor.totalLen(node + 0x20) = the real payload length: the 802.3 length field verbatim in mode != 0, orframeLen - 12in mode 0.descriptor.hdrLen(node + 0x1E) = 14 or 12 per the mode word.- dst MAC is additionally duplicated to node + 0x22 (0x5EA8), src MAC to node + 0x28 (0x5EB4).
The host therefore always receives the complete frame including bytes 12-13, in both modes. The
FCS is already stripped (- 4 at 0x5CAA). Padding is included in the buffer but totalLen is
authoritative.
Receive buffer size is fixed: POST-RX-BUFFER rejects any node whose descriptor.len != 0x5F0
(1520 bytes) with error -0x16 (0x6C82). 1520 comfortably holds a full 1514-byte Ethernet II frame,
so buffer size is not a constraint on TCP/IP. [V]
5. Broadcast / ARP - the one real obstacle at this layer [V]¶
GroupAddressFilterMatch @ 0x542C walks a singly-linked list at g_groupAddressListHead
(0x18942); each node is { +0 long next, +4 six-byte MAC }. It byte-compares all six bytes and
returns 1 on match, 0 otherwise. An empty list returns 0 for every group frame (0x5484).
There is NO hardcoded broadcast case. FF:FF:FF:FF:FF:FF is not special-cased in this routine or
anywhere in RCVCOMPLETE. A broadcast frame reaches the host only if:
- (a)
FF:FF:FF:FF:FF:FFhas been added to the group list by the host's SET-GROUP-ADDRESS command (0x6880 / 0x68A8), or - (b)
g_addressFilterEnable(0x18888) == 0, i.e. promiscuous.
Both are reachable with existing host commands, so no firmware change is required for ARP - but see the open question in section 9 about the LANCE's own hardware filter.
6. Corrections to earlier docs in this folder¶
| Doc | Stale claim | Correct reading |
|---|---|---|
| ETHII-HOST-PROTOCOL-SPEC-2026-07-25.md | "0x18888 Promiscuous flag, init 1" |
Inverted. Nonzero = address filtering ENABLED. Init 1 means NOT promiscuous. Evidence: 0x5D8C tst.w 0x18888 / bne 0x5D9C - on a MAC mismatch, nonzero takes the REJECT branch; the zero case falls into move.w #1,(0x38,A6) = accept. Same polarity at 0x5DDE. Renamed g_addressFilterEnable. |
| ETHII-HOST-PROTOCOL-SPEC-2026-07-25.md | "0x1888a mode-8023 flag; gates TX hdr-len" |
True but incomplete - it is a raw-12-byte-header vs 802.3-14-byte-header switch that also changes what the host is shown on receive (0x5E7C), and mode 0 is a full raw pass-through. |
| ENNS0-RX-FORWARD-ROOTCAUSE-2026-07-24.md sec 2 | "the 0x6034 branch ... advance the ring, re-append the buffer, yield" implying accept and discard differ in ring handling | Both accept AND discard reach the shared tail 0x5FF2 -> clear RMD -> 0x5FFC advance FREE/CONS. They differ only at 0x601A. Also: 0x5FFC is NOT dead code despite having no xrefs - execution RESUMES at the instruction after the jmp (A5). CORRECTED 2026-07-26: the reason is NOT a "coroutine yield". PLANC-MC compiled routines return to return address + 2 (movea.l (SP)+,A6 ; movea.l (SP)+,A2 ; jmp (0x2,A2)), which SKIPS the 2-byte 4E D5 jmp (A5). That trampoline is the error-unwind path, entered only when the runtime returns to +0. See the PLANC calling-convention section below. |
Both files have been annotated in place with dated correction notes.
7. TCP/IP capability matrix¶
| Capability | Status | Firmware evidence |
|---|---|---|
| Ethernet II receive | Supported (host config) | 0x5D0A - mode 0 skips gate 2 entirely |
| Ethernet II transmit | Supported (host config) | 0x60BC - no length word written; host owns bytes 12-13 |
| ARP receive | Supported, conditional | passes gate 2 in mode 0; needs broadcast MAC registered (0x542C) or filter off |
| ARP transmit | Supported | dst MAC is host-supplied at node+0x22 (0x60E0); no broadcast restriction found |
| IPv4 receive / transmit | Supported (mode 0) | same paths; no EtherType inspection exists |
| IPv6 receive / transmit | Supported (mode 0) | 86 dd absent from the image, so nothing blocks it either |
| Broadcast reception | Conditional | 0x542C has no broadcast case - see section 5 and open question O1 |
| Raw frame delivery | Supported | 0x5E72 - zero-copy, MAC header intact, full frame |
| Raw frame transmission | Supported (mode 0) | 0x60BC |
| Adequate buffers | Supported | 1520-byte RX buffers enforced at 0x6C82 vs 1514 needed |
| Unknown EtherType forwarding | Supported (mode 0) | nothing classifies, so nothing is selectively dropped |
| COSMOS coexistence | Needs ND-100 driver change | see section 8 |
LLC/SNAP IP encapsulation is not needed here and was not pursued: mode 0 gives ordinary Ethernet II directly, which is what real TCP/IP peers expect.
8. COSMOS coexistence - the actual constraint¶
0x1888A is a single global word. There is no per-frame, per-client or per-queue mode, and there
is exactly one receive ring (128 x 8-byte RMDs at 0x18008) and one host ready list (0x188D6).
Changing the mode does not create or select a second queue - it only changes which frames survive to
be delivered on the one queue. [V]
Consequences of running the card in mode 0 - CORRECTED 2026-07-26:
- COSMOS receive passes the firmware gate 2 unconditionally, but then dies one layer up: the
on-card ENCOS server (0xA18E) computes payload as
base + hdrLen, and withhdrLen = 12it reads the 802.3 length field as LLC DSAP/SSAP, fails the0xA8/0xA8/0x03test, and rejects the frame. [V] - COSMOS transmit breaks: the ENCOS server writes its LLC payload at
base+14(0x847E) and leaves bytes 12-13 for the firmware, which in mode 0 no longer fills them. [V]
The earlier claim in this section - that coexistence is achievable with no firmware change, by having the ND-100 build and parse the length field - is WRONG and is retracted. The ND-100 does not build the frame and never sees it; the ENCOS server on the card does both. Fixing this means patching the ENCOS server (which hard-codes +-14 at 0x83E6-0x849C, 0x8E50, 0xA18E, 0xADD4), not the ND-100.
Note also that COSMOS is identified entirely on the ND-100. The captured COSMOS payload begins
a8 a8 03 (LLC DSAP 0xA8 / SSAP 0xA8 / UI control 0x03), but no firmware code reads those bytes.
The card has no notion of COSMOS. [V]
9. Required host behaviour (the concrete recipe)¶
SET-MODE-FLAGS(handler 0x6786) with:word[0x18] = 0-> raw / no length fieldword[0x16] = 0(promiscuous) or keep 1 and registerFF:FF:FF:FF:FF:FFvia SET-GROUP-ADDRESS (0x6880 / 0x68A8)word[0x14] = 4-> keep the 60-byte minimum TX padding
ENABLE-RX-POOL, thenPOST-RX-BUFFERnodes of exactly 1520 bytes (0x5F0).- Transmit: supply
hdrLen >= 12with the EtherType as the first two bytes of the payload buffer; the firmware fills dst MAC (from the command node) and src MAC (from the station address). - Receive: read the whole frame from
descriptor.base;totalLenat node+0x20 isframeLen - 12.
10. Open questions - these feed the ENNS0 driver analysis¶
- O1 [U] - the decisive one. Whether the Am7990 LANCE's own MODE register (PROM bit) and LADRF
are programmed to accept broadcast.
STARTMA@ 0x5850 only clears0x18880and calls 0x503A; the actual LANCE MODE/LADRF programming was not traced. If the LANCE hardware filter drops broadcast, no host-level setting will help and ARP fails. Resolve before committing. - O2 [U] Does the ND-100 ENNS0 driver ever issue SET-MODE-FLAGS, and with what values? If it
hardcodes
word[0x18] = 1on every start, any Ethernet II configuration will be overwritten. - O3 [U] Does ENNS0 expose any host-side path that would let a second consumer post RX buffers / read the ready list, or does it own the ready ring exclusively?
- O4 [U] SET-MODE preconditions at 0x6770 that return
-0xAwere not decoded. - O5 [U]
g_txMinLengthPadMode(0x18886) has exactly one read (cmpi.w #4at 0x6110); other legal values unknown. - O6 [U] Consumer of the RX error event word
0x1894Cuntraced;txretry_listproducer/consumer untraced. - O7 [U] Vendor's official field names for the stats block offsets are not in this image; the labels below are descriptive, not Norsk Data's.
11. Statistics block offsets recovered [V]¶
g_nmaStatsBlock @ 0x1888C, 0x3A (58) bytes, source of the READ-STATS command. All counters are
saturating (cmp.w #-1 / bcc skip / addq).
| Offset | Size | Bumped when | Site |
|---|---|---|---|
| +0x14 | long | no free receive buffer (gate 3b) | 0x5ECA |
| +0x1C | word | CRC error (RMD1 bit 11) | 0x5F06 |
| +0x1E | word | framing error (RMD1 bit 13) | 0x5F3E |
| +0x20 | word | overflow (RMD1 bit 12 OFLO), also sets bit 1 of 0x1894C | 0x5FBA |
| +0x22 | word | buffer error (RMD1 bit 10 BUFF), also sets bit 2 of 0x1894C | 0x5F76 |
| +0x24 | word | length / format mismatch | 0x5D30 |
| +0x2A | word | runt (<60) or oversize (>1514) | 0x5CE2 |
| +0x2C | word | address reject | 0x5D9C |
+0x24 is the diagnostic to watch: it ticks once for every Ethernet II frame over 60 bytes that the mode word discards. If IP traffic is arriving and being silently dropped, this counter is the proof.
12. Ghidra database changes made during this analysis¶
Program: encos-ser-all-banks-68k.bin.
Disassembled (previously undefined bytes): 0x5EF4, 0x604C.
Functions renamed / documented:
- maybe_format_lance_descriptor -> LanceRxDescriptorClear (0x553C) + full doc block. Note it does
NOT set OWN; re-arming is done separately by 0x5B60.
- maybe_handle_group_address -> GroupAddressFilterMatch (0x542C) + doc block recording the
missing broadcast case.
- RCVCOMPLETE (0x5C42) given a full plate comment (purpose / inputs / outputs / global state /
control flow / what the frame parser does and does not do).
Globals renamed:
| Address | Old | New |
|---|---|---|
| 0x1888A | mode_include_length_field |
g_mode8023LengthField |
| 0x18888 | lan_mode_flag |
g_addressFilterEnable (polarity corrected) |
| 0x18886 | lan_function_code |
g_txMinLengthPadMode |
| 0x1885E | lance_mac_address |
g_stationMacAddress |
| 0x18000 | lance_rx_ring_ctrl |
g_lanceRxRing |
| 0x18408 | lance_tx_ring_ctrl |
g_lanceTxRing |
| 0x1888C | nma_stats_block |
g_nmaStatsBlock |
| 0x18942 | DAT_00018942 |
g_groupAddressListHead |
Structures created (category /encos_ethernet): LanceRmd (8 B), EncosFrameDescriptor (12 B),
EncosRxRingHeader (8 B, applied at 0x18000).
Comments added at: 0x1888A, 0x18888, 0x1888C, 0x1894C, 0x18000, 0x18408, 0x542C, 0x5C92, 0x5CA2, 0x5CD0, 0x5D0A, 0x5D14, 0x5D1C, 0x5D20, 0x5D2C, 0x5DF2, 0x5DFA, 0x5E02, 0x5E72, 0x5E7C, 0x5EF4, 0x5EFC, 0x5FF2, 0x601A, 0x6086, 0x679A, 0x6BB6, 0x6C82, 0x7026.
Bookmarks in categories EncosRxPipeline (0x5C42, 0x601A), EncosRxClassifier (0x5D20, 0x5DFA),
EncosRxDrop (0x5EF4, 0x5EFC), EncosRxFilter (0x542C), EncosModeFlags (0x1888A, 0x679A).
Not done: no enums were created - the Ghidra MCP interface in use exposes no enum-creation tool, so the RMD1 bit meanings and the mode-word states were recorded as comments instead.
Related¶
- ETHII-HOST-PROTOCOL-SPEC-2026-07-25.md - the card's host command/ring contract (corrected by section 6 above)
- ENNS0-RX-FORWARD-ROOTCAUSE-2026-07-24.md - the original gate analysis and the FCS double-count fix
- ENNS0-RXPOOL-PRODUCER-RE-2026-07-24.md - who fills the receive pool
- COSMOS-MULTI-NODE-NETWORK-2026-07-25.md - the working two-node COSMOS network
..\..\..\..\Installation\Communication\Ethernet\x\stripped\docs\- the rest of the 68000 firmware reverse engineering..\..\..\..\Reference-Manuals\Devices\ND-12.055.1 EN Ethernet II Controller.md- the card manual
Next step: deep analysis of the SINTRAN ENNS0 driver to answer O2 and O3 - whether the ND-100 side can be made to drive the card in mode 0 without breaking COSMOS.