Sunday, August 21, 2022

Booting PDT-11/150 from TU58s and TU58 emulators

   A post or so back, I wrote up how to connect a TU58 (or emulator) to a PDT-11/150. Works great. But, you can't boot the PDT from a TU58 (or emulator - from here on, TU58 means TU58 or emulator - OK?), so you are still dependent on the RX01(ish) drives to get the system going. But there are a lot of PDT-11/150s out there with no software on floppies available, or with dead floppy drives. A way to boot from TU58 would enable people to load software or use them without the floppy drives.

  A look at the technical manual for the PDT, available at...

PDT-11/150 Tech Manual

 showed that the startup code for the PDT is in two 1K X 8 mask programmed ROMS on the memory board. I took a squint at the ICs in question, and saw that they were socketed - a good start - I'm in no mood to desolder a chip I can't replace if it gets destroyed in the process. They were mask programmed ROMs, part number NS82S2708. There is an EPROM  equivalent of this ROM, with the same pinout - the 2708. No sweat, I figured - sounds like a part from the common 27xx EPROM family. I can write new boot software, burn it to 2708s, and Bob's my uncle. I'll be done in an afternoon! Alas, that was not to be. Turns out that the 2708 is an early design EPROM. It requires three different supply voltages, and almost no hobbyist grade EPROM burners support it (for sure, mine doesn't). Pro grade ones that would support it are damned hard to find these days, and really expensive.

  So, that's about how these projects always go - a rush of initial enthusiasm, followed by a punch in the face from reality. Fortunately, this is an issue that has been dealt with already, by arcade video game  and pinball machine enthusiasts. Arcade games and pinball tables from back in the day often came with 2708 EPROMs. These hobbyists researched it and worked out that these can be replaced by 2716 2KX8 EPROMs, with a little work. The 2716 is a more typical 27XX part -  no exotic voltages required, and almost all EPROM programmers support it (most importantly, mine does). The 2716 is twice as big as a 2708 - you can program the 2708 image into the top or bottom half - the instructions below assume the code gets burned into the bottom half. You could even burn different programs into the two halves, and use a switch to select which one is active.  No need for that on this project.

  Here's the pinouts for the 2708 and the 2716

          2708                   2716
       
+--U--+                +--U--+
      A7|1  24|Vcc(+5V)      A7|1  24|Vcc(+5V)  
      A6|     |A8            A6|     |A8
      A5|     |A9            A5|     |A9
      A4|     |Vbb           A4|     |Vpp
      A3|     |*CS/PE        A3|     |*OE
      A2|     |Vdd           A2|     |A10
      A1|     |Program       A1|     |*CE/PGM
      A0|     |Q8            A0|     |Q8
      Q1|     |Q7            Q1|     |Q7
      Q2|     |Q6            Q2|     |Q6
      Q3|     |Q5            Q3|     |Q5
Vss(GND)|12 13|Q4      Vss(GND)|12 13|Q4
 
      +-----+                +-----+


Purty close, nicht wahr? Looking at the pinouts, you can see how to use a 2716 in a 2708 socket. You have to...

 - Connect pin 21 to pin 24 (2716 requires Vpp pin be at Vcc for reading)

 - Connect pin 18 to pin 20 (connect both output enable and chip enable to Chip Select)

 - Connect pin 19 to pin 12 (this selects the lower half of the 2 K ROM. Connect 19 to 24 to use
   upper half of 2716 instead. 

 - Don't connect pins 18, 19, and 21 to the 2716 from the board . The 2716 would be
   discomfited by the crazy 2708 required voltages (-5 and +12) present on those pins.

  The way the arcade guys accomplished this was to use two additional sockets, plugged into each other. On one of them, the bottom one, that will plug into the board, they did the first three steps - carefully soldering jumper wires between the indicated pins. On the next socket up, they got rid of pins 18, 19 and 21 (if you use machined pin sockets, you can heat the pins with a small soldering iron and push them out of the frame). Then they'd plug the 2716 into the top socket, plug the top socket into the bottom socket, and plug the bottom socket into the board where the 2708 once made its home.

  Here's a site that explains this. Unfortunately, it's been archived so it doesn't have its pictures anymore, but it's the best rundown of the solution I found.

Adapter for 2708 to 2716 swap


 And if you're looking for 2716s, you can also use a TMS2516 for a 2716. I didn't have any 2716s in the giant box o' salvaged obsolete through hole pin ICs, but I had plenty of TMS2516s, and they are pin and voltage compatible. There's a long story about why TMS2516s are equivalent to 2716s, but TMS2532s are not the same as 2732s, but, it's got nothing to do with this project, so I'll skip it (for now...).

  Anyway, enough of this hardware talk. That reminds me, what are the three most destructive things in computing? A system programmer with a soldering iron, a hardware tech with a patch tape, and a manager with an idea - and I'm two out of three!

  So, first step, I need to get the current contents of the factory boot roms, so's I can add the TU58 boot code into the normal initialization process. Hmmm...my EPROM programmer won't even read a 2708... Not a problem. The PDT tech manual reports that the boot roms occupy the addresses 170000-173777. I just booted RT11 from disk and used ODT to read the contents of that address range. This was better than reading the ROMs on a reader anyway - if I had read the two ROMs directly, on the EPROM burner, I would have had the additional step of combining the two outputs into one file, since the ROMS contain the bytes of each word - one ROM has the even bytes, one ROM has the odd bytes. The ODT just gave me the words as the PDT sees them, as combined words.

  Now I needed to convert the listing of the ROM contents into MACRO-11, so I can see where to add my evil magic. I have several tools that will disassemble an RSX object file (I usually use ORCAM), but nothing that will do it to a string of words like ODT produced. I wrote an EDT macro to translate the ODT statements in the form

173242/074524
173244/062560
173246/071440

to 

        .word     074524      ;173242
        .word     062560      ;173244
        .word     071440      ;173246

  Here's the result of that, in case there's any other hardware hackers out there that want an unmolested ROM listing for reference.

pdtrom.mac

 And then I assembled the resulting file to a .obj file - which I could then input to the ORCAM utility. Well, the results were a bit of a mess (when you look at machine decoded Macro-11 and you see a bunch of floating point instructions, you know you have some hand work to do) . Since this code was written to fit in a limited space, it had all kinds of programming tricks in it that confuse automated disassembly tools. Things like using the numeric value of other instructions as literals for arguments , and the like. Some of the coding stunts didn't seem to make a lot of sense - for instance, in places, the programmer created his own JSR - RTS technique using branches and jumps instead of just using the actual instructions. One good thing I found - even though the code was littered with these space saving tricks, there was over 600 bytes of unused space in the ROM, so there wasn't really any need for exotic tactics. That's plenty of space to load the TU58 boot routine.

  Here's the partially, poorly disassembled source. Feel free to correct and expand on my efforts. I only did enough to get this project done. Much of it is wrong. Some of the comments are in error as well. It might serve a starting point for someone else. It might serve as a source of amusement for those more skilled than I at reverse engineering.

pdtdis.mac

  A lot of manual disassembly of the resulting mess  let me find a place to put the boot code, and a place to let the user indicate that they want to boot the TU58 instead of the RX01 drives.. There is an unused space from 171630 to 172776. The boot routine is small, so I decided to load it at an even address, for convenience sake - 172000 - still plenty of space starting there.

  For a boot routine, I adapted the boot code from TU58FS, by Joerge Hoppe, who credits work done by Don North and the M9312 boot code. It's important to credit other people's work, nicht wahr? Here's the boot code I used. It's pretty self explanatory - sets the line speed for terminal line 1, inits the TU58, sends a boot request, gets 512 bytes and stores 'em starting at address 0 - then jumps to 0 and starts executing.

ddboot.mac

  Now I need a way to invoke that code when I want to boot from the TU58. There is a place in the original boot code where, if neither disk is loaded, the system asks you if you want to boot disk 0 or 1 - that gives you a chance to load the disk and try again. If you answer 0 or just carriage return, it retries disk 0. If you answer 1, it retries disk 1. If you answer anything else, it asks you again. It only took changing a couple of words to alter that behavior to be, if you answer anything besides 0 or 1, jump to 172000 and do the TU58 boot. I use a capital G...for Gleason...I recommend you do the same.

  It looks like this...

  Unload both disks and power on. The system will say

Read error

Type start unit number (0 or 1):  

  If you type 0 or 1, it tries to boot...disk 0 or 1. If you enter anything besides a 0 or 1, it will jump to the TU58 boot code. A banner will print

PDT-11/150 TU58 Boot LKG V01A01

and it will try to boot from the TU58. 

 Here's what it took to make this happen. In the boot rom, I changed the code at lines 5 and 6 in the code snippet below

  Original:
        CMPB    (R1)+,R2        ;typed a 1?
        BEQ     3122$           ;then boot from PD1:
        CMPB    (R1)+,R2        ;typed a 0? 
        BEQ     3120$           ;then boot from PD0:
        CMPB    (R1)+,R2        ;compare for space input
        BNE     3042$
3120$:  CLR     R3 
3122$:  MTPS    #340

*******************************
Modified:
        CMPB    (R1)+,R2     ;typed a 1?
        BEQ     3122$        ;then boot from PD1:
        CMPB    (R1)+,R2     ;typed a 0? 
        BEQ     3120$ 
        JMP     @#172000     ;not 0 or 1,jump to our TU58 boot code.
3120$:  CLR     R3           ;clear r3 to boot from unit 0
3122$:  MTPS    #340

  In binary, this change amounts to swapping lines

       .word   122102  ;173114
       .word   001351  ;173116

with
       .word    137     ;173114
       .word    172000  ;173116

 

  This boot rom should work with a real TU58, or a TU58 emulator. I have only tested it with ETU58, the RSX TU58 emulator I wrote a while back (see previous TU58 post for details). A few small changes were required to ETU58, to support a boot request from the PDT. This new version of ETU58 still supports booting from the disk like normal, and accessing the DD devices just like it did before.

  OK, how to put it all together? First, mod those two lines in PDTROM.MAC and save as file NROM.MAC (for new ROM) Then assemble it to produce a listing file. You don't need an obj file.  Use LISPAR (see a previous blog post for the Macro-11 List File Parser utility) to convert the listing to an Intel format load file, using the /SP (split) switch on the output to produce odd and even output files (that contain the odd and even bytes of the file, that go into odd and even EPROMs).

>mac ,nrom=nrom
>run lispar
MLP>nrom/sp=nrom

  That produces files NROM.EVN and NROM.ODD.

  Assemble DDBOOT.MAC to produce a listing file. Use LISPAR to produce odd and even Intel format files. Use /ADR:1000 to tell it where we want the code in "EPROM address space" - that will cause it to appear at 172000 when everything gets done.

>mac ,ddboot=ddboot
>run lispar
MLP>ddboot/sp=ddboot/adr:1000

  Edit nrom.odd and nrom.even. Replace the two lines that go to address 1000 with the two lines in each of ddboot.odd and ddboot.evn. Save the files and burn them to two 2716 or 2516 eproms. OK, that's a lot of work. If you're good with the state of the code as it is, I provide the current version of two files that need to be burned to the EPROMs below. 

NROM.EVN

NROM.ODD

Then replace the ROMs on the memory board with these EPROMs, inserted into the double scoket adapter described above. The Odd EPROM goes on the left, if you're facing the front of the machine - the even EPROM goes on the right. Make sure and match the "U" notch orientation of the ROMs - the "U" notch faces the front of the machine.

  Then, connect the TU58 or emulator to Terminal 1 on the PDT. Remove the disks from the two drives and power on. When it asks boot from 0 or 1 - enter any character, and it should boot from the TU58.

  So, sweet - everything works and we're all done with this project...well, not quite. When I went to put the lid back on the PDT...the double socket style EPROM adapter discussed above  sticks up too far for the top to fit.  I thought about this problem for a bit. I have a dremel tool and lots of cutoff disks....but no, as much fun as putting a hole in the top would be, it would look terrible and allow junk to fall down onto the memory board. A little more study showed that the only function of the upper socket is to make sure pins 18, 19 and 21 don't get connected to the circuit board. I can get the same effect  by cutting  pins 18,19 and 21 off of the EPROM, and keep the lower socket with the wiring adds on it. That lowers us by one socket. Why didn't I do this from jump street? Why did the arcade and pinballs guys use two sockets? Because, once you mangle up the chip pins, you can't erase and rewrite the EPROM  anymore....and believe you me, the new EPROM code took several edits before it worked.

 And, like I said above, my RSX TU58 emulator, ETU58, needed a few changes to support the boot request from the PDT. I named this version of it NTU58 (New TU58). Here it is...

ntu58.mac

To use, it's just like ETU58, from previous blog post. Build instructions are also in the file itself.

  If any of the 4 or 5 people in the world who are PDT-11/150 AND TU58  hobbyists try this, let me know if you have any problems.