So what will happen, when this all works, is that the sun 3/80 will network boot my code (using rarp and tftp). Then that code will turn around and do exactly the same thing -- run rarp and tftp to boot some other standalone code. It will need to be "some other" code because it will be loaded to and run at a different address than the 0x4000 that the test standalone will be running at.
Once all this works, I will take the next step (probably) and work up a DHCP client to replace RARP.
Doing all this has been an excellent way to really understand things that go on with the bootrom device drivers, especially the ethernet. It has also been a great chance to dig into some Sun 3/80 details I never looked at closely before.
Testing revealed some surprises with virtual address faults to unexpected addresses. The tftp code simply uses a block of memory at 0x3000 for the data structures it needs (a better scheme would use some kind of allocator). The code as trying to use the 3/160 rom base address to access the romvec table -- this was a simple change.
Now I have added a multitude of printf statements to see what the code is doing. It is trying to do the RARP, sending a packet and awaiting a reply.
I fire up wireshark and am pleased to find that "rarp" makes a perfectly good capture filter. It sees the real bootrom sending a rarp request, and my linux machine replying. But it does not see a second rarp request from my test code (though the printf statements indicate it things it sent a packet), so that is the problem I am now troubleshooting.
The lance chip has a 24 bit addressing capability. So what happens as far as the upper 8 bits in the Sun3 memory world. As near as I can tell this happens:
on the sun 3/160 the upper 8 bits get set to 0x0f on the sun 3/80 the upper 8 bits get set to 0xffThe bootrom code uses a simple memory allocator (in monalloc.c) to dole out memory suitable for DMA. It starts (on the 3/80) from a base address of 0xfff0_0000 -- note that the virtual address map has this mapped to physical memory at 0x00ff8000 which is near the top of the actual 16M of physical memory on my sun3/80. This is so for 3 pages (24K) then the mapping does other things. Perhaps 24K is adequate for the lance structures.
On the 3/160 the DMA memory allocator starts off at 0x0ff0_0000, but I have not worked out the full details of the address mapping as I have for the 3/80. But I do know the if_ie.c driver works just fine using that, so I am not worried much about it.
We aren't expecting a packet, so this must be a broadcast that came our way. What does the driver do to filter out broadcast packets? When waiting for a REVARP reply, it does a full chip reset after any packet that it does not recognize. Certainly a brute force approach, but OK for a bootrom I suppose.
Once we get past REVARP and start running TFTP, we get input via ip_input, which gets packets from the lance "poll" routine. The poll routine only watches the RINT bit in the lance CSR, so it clearly doesn't expect the MISS bit to be set, nor does it check the ERR bit. It expects to receive a packet and then let TFTP sort out whether it is a broadcast packet that it doesn't care about. The tftp code has a list of reasons to ignore packets. It wants only in-sequence DATA packets.
But all this is somewhat beside the point. Our receive buffer ring must be faulty for the chip to decide there is no buffer for the packet, whatever it might be.
I start fooling around looking at the state of the lance chip and its memory data structures as left by the sun 3/80 bootrom. I see the CSR set to 0x4 (the chip is stopped). The buffer rings make sense and are in memory at 0xfff02000, at least the init block is. The Rx and Tx rings are at 0xfff05390 and 0xfff053d8. Interestingly, there are 8 buffers in the Rx ring (the driver I have source for only uses 2 buffers). Here is a clumsy dump of the Rx ring:
RMD 0 FFF05890: 00002046 00000080 000000F0 0000F9C0 00000000 RMD 1 FFF05898: 00002686 00000080 000000F0 0000F9C0 00000000 RMD 2 FFF058A0: 00002CC6 00000080 000000F0 0000F9C0 00000000 RMD 3 FFF058A8: 00003306 00000080 000000F0 0000F9C0 00000000 RMD 4 FFF058B0: 00003946 00000080 000000F0 0000F9C0 00000000 RMD 5 FFF058B8: 00003F86 00000080 000000F0 0000F9C0 00000000 RMD 6 FFF058C0: 000045C6 00000080 000000F0 0000F9C0 00000000 RMD 7 FFF058C8: 00004C06 00000080 000000F0 0000F9C0 00000000So, the buffers sit between the init block and the descriptors, which is fine of course. The flags are all 0x80, which is the OWN bit set (so the lance is free to use these).
The transmit descriptor looks like this:
TMD 0 FFF058D8: 00005246 00000003 000000F0 0000FFC4 00000000 (60)
While the Receive buffers are all 1600 bytes in size, the Tx buffer is only 60 bytes! I suppose this is adequate for ARP, RARP, and TFTP. This is different than the code I have where both Rx and Tx buffers are 1600 bytes in size.
Here the Tx flags are 0x03 which are STP and ENP. The OWN bit is not set, which also makes sense, the LANCE has finished sending and has handed the buffer back to the driver.
LE csr0 = 000090B2Next I try repeating the initialization and then turning on the start bit. I see:
tjt - lereset init loop start CSR0: 00000001 tjt - lereset init loop done CSR0, timeout: 00000181 999 tjt - lereset init loop done CSR0, timeout: 00000001 999 LE csr0 = 000090B3 LE csr0 = 000090B3This is exactly what I see using the source driver. I am surprised. This makes me think that the chip setup and data structures are fine and there is some other magic that is needed that I need to learn about. This may require studying the 3/80 bootrom disassembly.
sys/sun3x/locore.s sys/sunif/if_le.cDoing grep on DVMA or dvma yields interesting things.
The "ENABLE" register is very different on the sun3x. For one thing is gets assigned a "plain old" address among the OBIO (on-board IO) registers, which end up needing to be mapped into the virtual address space when the MMU is enabled. SunOS maps it to 0xfedf8000, but the bootrom has a different place for it:
Sys ENA Reg 0xFEF16000: 0x61000000:On the sun3 architecture it is an 8 bit register at 0x40000000 in a special address space and must be accessed via a movsb instruction. On the sun3x, it is a 16 bit register at the address shown above.
Relevant files in an old version of the NetBSD sources are:
NetBSD-2.0/usr/src/sys/arch/sun3/sun3x/dvma.c NetBSD-2.0/usr/src/sys/arch/sun3/dev/if_le.c
I find this comment in the NetBSD sources:
* Enable DVMA in the System Enable register. * Note: This is only necessary for VME slave accesses. * On-board devices are always capable of DVMA.
Tom's Computer Info / tom@mmto.org