• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

SEthernet and SEthernet/30: A new take on PDS Ethernet

Melkhior

Well-known member
If anyone wants to look at my code and poke fun at review
One comment: you've dropped the mac ABi (passing values through registers) in favor of C (stack), but the '030 needs all the help it can get performance-wise. Once the code is stable, I'd suggest reinstating a register-based ABI wherever possible to save a bit on time, at least for function on the 'critical path' (control, perhaps status, callbacks, interrupt handler). Fewer instructions & fewer bus cycles. Retro68 mechanism of using pragmas is reasonably clear and readable for that purpose.
 

cheesestraws

Well-known member
Disabling the chip's interrupt line in the glue logic until the driver has signaled that it's ready feels pretty bad too, although Macs pull a similar trick to temporarily map ROM into RAM during early boot, so I don't feel *too* guilty about using it.

You say "nasty hack" I say "period-appropriate engineering methodology", potato potato, etc
 

halkyardo

Well-known member
One comment: you've dropped the mac ABi (passing values through registers) in favor of C (stack), but the '030 needs all the help it can get performance-wise. Once the code is stable, I'd suggest reinstating a register-based ABI wherever possible to save a bit on time
Yeah, at one point I started wondering if the compiler was doing something weird, and tried to get rid of as many "Retro68-isms" such as that to simplify things. Turns out it was indeed doing something weird, but nothing to do with #pragma parameter. A lot of that code is due for an optimization pass once it's working.

I did notice that a lot of the time, at least in my debug builds with optimizations turned off, the register arguments just ended up being pushed onto the stack at the beginning of the function anyway.

Interestingly, in my IIfx, I'm already getting write performance (as measured by LanTest against a Netatalk 2.x AFP server) that's not far off the NuBus ethernet card I have in that machine - 450ish kbyte/s versus 500 or so. Read performance is a lot worse (300-350, versus 500), but given all the stack nonsense that I'm doing in my protocol handler callbacks, that's somewhat understandable. This is on a debug build with all optimizations turned off, too. I'm quietly hopeful that with some tweaks, it'll outperform a NuBus ethernet card.

You say "nasty hack" I say "period-appropriate engineering methodology", potato potato, etc
Serenely adopting Woz Mindset.
 

halkyardo

Well-known member
And some proper success! Figured out the issue that was stopping async writes from working - and it was a subtle one!

For one, Inside Macintosh makes no mention of it that I can tell, but the IODone routine that you call to signal completion of an asynchronous IO operation, doesn't follow the standard register-saving conventions! If you try to do things after calling IODone, depending on what completion routine gets called, you can find that D3, A2 and A3 have been trashed.

The second was a silly mistake on my part; I was acknowledging the transmit-complete interrupt *after* returning from IODone. This was all well and good, but if a completion routine queued another transmit, that transmit could complete *before* IODone returned, meaning that I was wiping out its transmit-complete interrupt too. Oops.

With a bit of mild optimization (using register parameters in a few places, and moving a bunch of small frequently-called functions into headers so they could be inlined), it seems to be stable, and by the numbers, it performs comparably to a 10 Mbit NuBus card (writes are appreciably faster, reads are a little bit slower). I'm sure that with some more tweaking it'd be possible to squeeze more out of it - right now it's very much written to be (at least somewhat) easy to understand and reason about, rather than going for flat-out performance.

The next step, I suppose, is to try and do the same for the SE. I've got the parts, I just need to get it all put together and make the necessary driver tweaks. Should be fun!
 

Phipli

Well-known member
And some proper success! Figured out the issue that was stopping async writes from working - and it was a subtle one!

For one, Inside Macintosh makes no mention of it that I can tell, but the IODone routine that you call to signal completion of an asynchronous IO operation, doesn't follow the standard register-saving conventions! If you try to do things after calling IODone, depending on what completion routine gets called, you can find that D3, A2 and A3 have been trashed.

The second was a silly mistake on my part; I was acknowledging the transmit-complete interrupt *after* returning from IODone. This was all well and good, but if a completion routine queued another transmit, that transmit could complete *before* IODone returned, meaning that I was wiping out its transmit-complete interrupt too. Oops.

With a bit of mild optimization (using register parameters in a few places, and moving a bunch of small frequently-called functions into headers so they could be inlined), it seems to be stable, and by the numbers, it performs comparably to a 10 Mbit NuBus card (writes are appreciably faster, reads are a little bit slower). I'm sure that with some more tweaking it'd be possible to squeeze more out of it - right now it's very much written to be (at least somewhat) easy to understand and reason about, rather than going for flat-out performance.

The next step, I suppose, is to try and do the same for the SE. I've got the parts, I just need to get it all put together and make the necessary driver tweaks. Should be fun!
I don't know how you've managed so much in so little time!

Do you offer introductory courses on driver writing for vintage OSes? 😆
 

cheesestraws

Well-known member
For one, Inside Macintosh makes no mention of it that I can tell, but the IODone routine that you call to signal completion of an asynchronous IO operation, doesn't follow the standard register-saving conventions! If you try to do things after calling IODone, depending on what completion routine gets called, you can find that D3, A2 and A3 have been trashed.

Wow, that's nasty. Not even the normally-reliable THINK Reference mentions this, as far as I can see!
 

halkyardo

Well-known member
I don't know how you've managed so much in so little time!
Mostly just an obsessive nature, I think!
Do you offer introductory courses on driver writing for vintage OSes? 😆
Ha, you know, that was kind of one of the reasons why I wanted to do this - to better document how to do it. Unfortunately ethernet drivers are a little bit unusual compared to the way drivers are 'supposed' to work on the Mac OS, so I'm not sure how good it will be as a general example, but I hope that my source and comments will make it a bit easier to understand.

One of these days I'd love to do a proper writeup on it too.

Wow, that's nasty. Not even the normally-reliable THINK Reference mentions this, as far as I can see!
It's not even directly noted in the leaked source that's floating around! It's buried in a comment for an internal function that IODone calls!

Finally built up an SE board today and was really excited to try it out, but as it turns out, I've snatched defeat from the jaws of victory, and managed to design the board with the PDS slot pinout backwards. So that's not going to do anybody much good. 🤦‍♂️

In theory I could move the PDS connector to the other side of the board and try it out (I only got it backwards on one axis), but I don't have enough parts to build another board, and desoldering a 96-pin connector to modify the one I did build, doesn't sound like much fun at all. So I think development for the SE is going to be put on hold a little bit further.

I've got some time off work over the holidays, and I think I'm going to make it my goal to get a new hardware revision finalised before the new year and focus on that rather than putting effort into trying to get my known-to-be-buggy existing board to work.
 

halkyardo

Well-known member
Well, still no Revision 1 or SE board, but progress has continued in the background. I set up a bunch of disk partitions on my SE/30 to try out a range of operating systems and configurations, and after a bit of patching, things are looking good!

I'm focusing my support on System 6.0.8 through 7.5.5, which gut instinct suggests would be the range of operating systems most 'reasonable' people would be using on both the SE and SE/30. I know the SE/30 goes back to 6.0.4 (?) and the SE goes back even farther, and if someone can come up with a compelling reason to test and support them, I'd be happy to, but I don't want to stretch myself too thin, and I feel like developing for anything much older than 6.0.8, you start to run into "oh wow this OS feature that I use everywhere doesn't exist" kind of territory. I've already noticed that even though the Shutdown Manager is supposed to be supported on 6.0.8, and I'm using it exactly how IM V says to, it doesn't seem to work, which ruins my mitigation for that spurious interrupt bug (which should be resolved in the next hardware rev anyway, but still..)

OSStatus
6.0.8Works after installing Network Software Installer 1.4.4 (install AppleTalk and EtherTalk NB driver).
7.1Works after installing Network Software Installer 1.4.4 or 1.5.1 (install AppleTalk and EtherTalk NB driver)
7.5.x with Classic NetworkingWorks after installing Network Software Installer 1.5.1 (install EtherTalk NB driver only, answer "no" when it asks you if you want to replace the newer Network control panel already present in the system)
7.5.x with Open TransportWorks out of the box, but is significantly slower than Classic Networking

In all relevant cases, tested under 24-bit and 32 bit mode, VM on and off. I should add, 'Works' should be read as 'Works after copying the SEthernet/30 driver into the Extensions folder').

The Network Software Installer aspect is a bit frustrating - it provides the .ENET 'driver shell' that loads the real ethernet driver, but it only seems to install it if it's installing drivers for an Apple ethernet card - for my card, you have to do a Custom Install, tell it to install the driver for an Ethertalk NB card or something, and THEN install my driver. I hadn't run into this problem before, since the OS install on my SE/30 had started life on my IIfx, which had ethernet drivers already installed. But for a clean install, it's a bit of a pain.

It's clear that the Network Software Installer components must have been part of a developer kit that Apple provided to ethernet card vendors; looking at the installer scripts for the Network Software Installer, and driver disks from Dayna and Asante, a lot of the resource IDs, messages, and 'installer action' code resources look to be identical or similar - they all provide the same .ENET 'shell' and AppleTalk bits, just with their own drivers instead of Apple's.

Trawling through developer CDs hasn't yielded anything beyond the standard Installer SDK, sadly. I wonder if my best bet would be to just hack up a version of the Network Software Installer to include my drivers, rather than trying to build an installer from first principles.
 
Last edited:

halkyardo

Well-known member
And with some rather hideous hackery, we have an installer! https://github.com/rhalkyard/SEthernet/tree/main/installer

I DeRez'ed the installer script from Network Software Installer 1.4.4, and with a bit of reverse-engineering, crudely chopped out the Apple drivers and replaced them with my own. It is even able to detect my card and install or not install the driver as it sees fit! Still need to work on how the SE driver will fit into this scheme - since I can't autodetect it with the Slot Manager, and there should probably only be one .ENET0 driver in the System file at a time I'll probably have to do a bit of trickery with custom actions to handle that, but looking at how the other vendors have done that gives me a good basis to go on.

It's funny, after all that, the "hard part" was figuring out how to automate building something in MPW on a non-Mac! Ended up throwing together a bit of a Rube Goldberg machine that (ab)used the MPW UserStartup script to do everything hands-free inside Mini vMac.
 

NJRoadfan

Well-known member
Don't assume 3rd parties had a nice SDK for this. Your assumption of vendors hacking up Apple's installer is likely what happened. It wouldn't be the first time someone had to do this simply because Apple's documentation was non-existent.
 

eharmon

Well-known member
And with some rather hideous hackery, we have an installer! https://github.com/rhalkyard/SEthernet/tree/main/installer

I DeRez'ed the installer script from Network Software Installer 1.4.4, and with a bit of reverse-engineering, crudely chopped out the Apple drivers and replaced them with my own. It is even able to detect my card and install or not install the driver as it sees fit! Still need to work on how the SE driver will fit into this scheme - since I can't autodetect it with the Slot Manager, and there should probably only be one .ENET0 driver in the System file at a time I'll probably have to do a bit of trickery with custom actions to handle that, but looking at how the other vendors have done that gives me a good basis to go on.

It's funny, after all that, the "hard part" was figuring out how to automate building something in MPW on a non-Mac! Ended up throwing together a bit of a Rube Goldberg machine that (ab)used the MPW UserStartup script to do everything hands-free inside Mini vMac.
You've done the work already, but if you want to escape Mini vMac, you might try: https://github.com/Treeki/mpw-emu/
 

halkyardo

Well-known member
Don't assume 3rd parties had a nice SDK for this. Your assumption of vendors hacking up Apple's installer is likely what happened. It wouldn't be the first time someone had to do this simply because Apple's documentation was non-existent.
Ha, yeah, good point. I noticed that the install script from an Asante driver disk I looked at has a bunch of 'dead' rules related to an A/UX driver shipped on Apple's Network Installer disk, despite the fact that they don't include any A/UX drivers!

You've done the work already, but if you want to escape Mini vMac, you might try: https://github.com/Treeki/mpw-emu/
Huh! I'd looked at MPW-emulation tools before, but they all seemed to require a Mac OS host. Might have to look a bit closer at this one, because somehow I'm a vintage-Mac enthusiast who doesn't own a single 'modern' Mac!
 

Mk.558

Well-known member
I know the SE/30 goes back to 6.0.4 (?) and the SE goes back even farther, and if someone can come up with a compelling reason to test and support them, I'd be happy to, but I don't want to stretch myself too thin, and I feel like developing for anything much older than 6.0.8, you start to run into "oh wow this OS feature that I use everywhere doesn't exist" kind of territory.

The SE without the FDHD / SuperDrive upgrade will go back to System 1.1/Finder 1.1g, which means it could probably boot 0.97 too, but I only tried S1.1/F1.1g. There's no reason to support anything lower than System 6 because MacTCP requires System 6 to begin with. The early stuff like TOPS Terminal or NCSA Telnet 2.5 could probably be hacked to work with it, but there's no real reason to.

Trawling through developer CDs hasn't yielded anything beyond the standard Installer SDK, sadly. I wonder if my best bet would be to just hack up a version of the Network Software Installer to include my drivers, rather than trying to build an installer from first principles.

I'd recommend that approach. The Installer SDK is such a heap of garbage with botchjob layered over botchjob, garbage ass documentation and confusing mess that if you could make it so it's just a simple drag and drop that'd be easier than fooling around with that thing.
 

halkyardo

Well-known member
I'd recommend that approach. The Installer SDK is such a heap of garbage with botchjob layered over botchjob, garbage ass documentation and confusing mess that if you could make it so it's just a simple drag and drop that'd be easier than fooling around with that thing.
Yeah, the installation situation is unfortunately a bit complicated. The driver for the SE/30 card can be installed drag-and-drop into the Extensions folder, but only if the EtherTalk Driver from a late (1.4.x or 1.5.x) version of the Network Software Installer has been installed previously, which by default only gets installed if an Apple ethernet card is detected in the system. So a 'drag and drop' install of the driver for the SE/30 would actually be "manually install the Ethernet NB drivers from this disk first, THEN drag and drop."

For the SE version of the driver, it looks like it has to be a DRVR resource in the System file, so drag and drop will never be an option there (and ResEdit-ing the System file doesn't work very well).

However, my hacked up version of the Network Software Installer seems to work pretty well - it's able to detect the SE/30 version of the card and install drivers AND the necessary EtherTalk support bits automatically. It's also able to install the SE drivers, but I haven't written a code resource to autodetect that yet. It's ugly, but I've confirmed that it's able to take a clean install of System 6 or 7 with no ethernet support from 0 to working without any extra faffing about. Which is basically all we really need from it.
 

halkyardo

Well-known member
With my SE/30 out of commission until I can find replace whatever went bang in its power supply, I thought I'd turn my attentions towards the long-neglected SE version of the ethernet card. My first attempt revealed a fairly glaring mistake in that I'd got the PDS connector pinout backwards, but after a bit of thinking, I realised that if I just installed the connector on the 'wrong' side of the board, it would work.

So I did that, and was immediately greeted with yet more timing issues 🙃. Turns out that there's an intensely annoying incompatibility between the '68000-like' bus mode of the ENC624J600, and the actual 68000 bus: on a read cycle, the 68000 asserts its address and data strobes simultaneously, but the ENC624J600 datasheet specifies a minimum 1 nanosecond delay between the chip being selected (derived from /AS and the address bus), and a data strobe being asserted. And even though it's only a nanosecond, if that delay isn't there, reads return garbage.

Thankfully, my new toy (an HP 54503 oscilloscope, picked up broken for $40 from my local surplus place and fixed up over the weekend), was very helpful in figuring it all out. It's even got a 68000 in it as well!

1705632819370.jpeg

On the SE/30 version, the propagation delay through my 3 GALs of glue logic meant that I'd included that delay by accident while trying to fix something else, but the simpler glue logic on the SE meant that everything happened all at once. I got around it by using a feedback pin on the GAL to essentially force an extra propagation delay before the data strobes are asserted, but that's going to complicate things a bit for my CPLD-based reimplementation of the design. I suppose for that kind of a short delay, just sticking a couple of inverters on the data-strobe lines might be enough to do the trick, but it's really annoying to have to do that!

In any case though, I've got something working, and after a few tweaks to the driver, we have functioning ethernet! The performance figures are interesting compared to the results I got on the SE/30 - for small repetitive operations, it's fairly consistently a bit slower than half the speed of the SE/30, but for bulk data transfer it actually holds its own pretty well - not quite as fast of course, but surprisingly close given the slower CPU!

Picture 1.gif

This was a really heartening pick-me-up. After all my frantic activity on this project for the past couple of months, I was starting to burn out and was struggling to find the motivation to keep working on it - especially before I realised that I could salvage my prototype SE card by mounting the PDS connector upside down.

There's still a ways to go - these prototype boards still have some major hardware bugs that I'm kludging around, and I really need to get on with that new hardware revision for both of them. Though I suppose I'd better fix my SE/30 first, so I have that machine available to test cards in. The joys of retrocomputing, eh?
 

Melkhior

Well-known member
that I'd got the PDS connector pinout backwards
It's annoying, isn't it? Had that happen with the MC68060 pinouts I found on the web... and then promptly made the exact same mistake creating a footprint for the MC88110! Grrrr.

that's going to complicate things a bit for my CPLD-based reimplementation of the design. I suppose for that kind of a short delay, just sticking a couple of inverters on the data-strobe lines might be enough to do the trick, but it's really annoying to have to do that!
Can't you just the same trick and connect the /CS output of the CPLD to an input pin of the same and use that to add an extra delay? Or would that be too long with a full CPLD pass-through delay?
Alternatively, you can probably make do with a single inverter, the CPLD can do the first inversion internally :) Or a non-inverting driver like the 74LVC1G07, which has a better worst-case latency than the 74LVC1G04.

Have you settled on a CPLD? With XIlinx discontinuing the XC9500XL family, it's becoming a problem for 5V projects :-(

In any case though, I've got something working, and after a few tweaks to the driver, we have functioning ethernet!
Congratulations! That's another impressive results - even more so than the SE/30 I think, the architecture of the SE/30 is more suited to expansion.
 

demik

Well-known member
Nice job. I would have gone with two hates of a 74HC14/04 or something as far as the delay goes. Or a 74LS31 if precision is needed.

How do you handle interrupts on a SE ? Just create another level with IPL0-2 lines that isn't used and put a vector there ?
 

Phipli

Well-known member
because somehow I'm a vintage-Mac enthusiast who doesn't own a single 'modern' Mac!
You might be surprised how many of us like that there are. Apple seems to have stopped making the type of computers I like. I'm a three expansion card, 3 hard disks kind of person, generally like towers, but not that fussed. IIci, Q650, 8100, 8600 kind of vibe...

Where is my computer Apple? You don't seem to have made me one since 2012? And that was stupidly expensive.

But that is an old discussion and off topic! Sorry :)
 
Top