The day was bright and sunny, and there was a bit of extra spring in everyone’s step at Adaptive. It was the early summer of 1990 and everything was hustling and bustling as the different departments were getting more into the production of the new product, the STM/18.
Prem and his hardware elves were pretty far along in their design. They were using silicon from Tellabs, a Chicago company that made equipment for phone companies. Audrey MacLean and Charlie Giancarlo has deftly convinced Tellabs that the STM/18 didn’t compete with them. And it didn’t. We were selling to large companies who wanted to implement their own corporate phone network.
Another group was busy designing the software. It would be some months until they worked out all their base design. Once done, they would start to code and test it on the Sun 3/60s that populated the California cubicles.
I was oblivious to all this because my focus was getting my embedded version of Unix working on the new hardware for the STM/18’s controller.
I kept my head down in my cubicle, which was getting tight. Under the table, there was a cardboard box with a bunch of odds and ends. There was the Sun 3/60 on my desk, along with a VME card chassis with our target MVME147 card inserted and a panel with six RS–232 25-pin serial connectors. There was also a power supply, disk drive, and 1/4" tape drive, sans case, with the SCSI ribbon cable strung between them. I had a second tape drive, a SCSI, connected to my Sun as well.
I had the target system, the MVME147 with its development debugger ROM, already set up and ready to use. My cross compiler was running and creating executable files. I’d also written a program, srec, that took the executable a.out file and created a Motorola standard S1S9 file. I could even load these binaries and run them in the system using a serial RS–232 cable.
The first program did nothing but load some value, do an add operation, and store it back again. I could single step this tiny program in the debugger to check that my compiler was operational.
I was using the MIT set of tools they had ported to the 68000 using Steve Johnson’s portable C compiler (PCC). This saved me a lot of work. For a completely new port, one has to consider the time it takes to design the calling sequence and stack frame that the compiled code will use. Then there are the changes that need to be made to PCC to get it generating code for the new machine. Most of this is simple work, almost done by rote, but the design of the stack frames and function calling sequence takes some creativity to get a fast implementation. The MIT tools saved me several weeks of work.
About the same time that I began using these tools, I noticed an odd building in our office park. The complex on Seaport Boulevard was close to the bay. Steve Job’s new company Next was across from the entrance, and on the other side of those was a small marina with a few dozen small sailboats.
In the other direction were two large two-story buildings built by Network Equipment Technologies, the company Audrey and Charlie had spun Adaptive out of. Just beyond that was the odd building.
It looked like a warehouse with an arched roof and high, featureless walls encircled by a guardrail. If that wasn’t strange enough, security guards patrolled the tops of the walls—with machine guns!
I asked about it. There was such a vast number of differing opinions that I realized that no one knew what it was.
Back in my cube, once the target and tools were in place, the actual work of the port could start. Unix is inextricably intertwined with the local disk. It boots from it. I need it as its root. I swap programs out to it. It must have a minimum of a disk to even boot.
This means that I had to get a sizeable chunk of stuff onto the disk before the machine could boot. At this point, I could only move data to our target system via a 1,000 byte a second serial link. We wouldn’t want to do that a lot.
The first Unix, the one written on the PDP–7, was moved over a bit at a time with paper tape. Tools were written on a General Electric machine, punched on the paper, and read into the PDP–7, writing the programs onto the machine’s tiny disk drive. As soon as the kernel, file system, editor, and assembler were on the system, it became self-sustaining. Even though the version I was using was minuscule by today’s standard, it was still too large to use the original technique.
The normal installation method in those days was to use a tape drive. Although they are a thing of the past, these drives were ubiquitous. For much of my career, I used a nine-track 1/2“ reel to reel, the kind you might see in an old movie. By 1990 the 1/4” QIC cassettes, connected over the SCSI bus, were everywhere.
Crammed into my overflowing cubicle were two tape drives: one on my Sun and the other on the bus connected to the target board. Can you guess what I planned to do?
A tape could hold several files, each terminating with an end-of-file marker and out-of-band symbol. By writing just beyond the end-of-file marker, I could assemble several files.
The first file would be a bootstrap program that allowed another file on the tape to execute. After booting off the tape, the program would prompt for the device and file number to run. The boot program would rewind the tape, then read until end-of-file until it got to your file. It would then be loaded into memory.
One of the files would be an image of the program that creates file systems. Called mkfs, this program put the superblock, inode table, and an empty root directory on a raw disk device. The source code for the program had some ifdefs to prompt for the parameters instead of getting them from the command line.
The tape’s third file was the user program restore. This read in the dump of a file system and wrote it onto the raw disk. Mkfs makes the file system and restore fills it with our initial system.
Since I was using the Sun as a donor system, it’s easy to get the compliment to restore, dump, to copy a subtree from the Sun to the donor’s tape drive.
So, boot file, make file system program, restore data program, and a file with the data to restore makes up the tape used to move the port to the target disk.
But all that depends on having a working SCSI driver for the ’147 card, and a serial driver, for that matter. All this needs to be written first.
One rule of this kind of development is to go incrementally, building on knowledge learned by a large number of small additions to the software. Fred Brooks said it right when he declared that software isn’t written or engineered—it’s grown.
I read all the documentation on the Western Digital 33C93 SCSI controller. I liked that its simple design gave me a lot of control over what was put on the SCSI bus. A review of SCSI allowed me to bone up on what I had to do to get a SCSI driver working.
First, though, I had to get a serial port driver working. The debugger ROM used one of the ports, but I needed another one to be the console for the Unix port.
This is a good time to talk about device drivers. Few programmers have had the opportunity to work with device drivers, and fewer had that opportunity back when the devices were simple and relatively easy to write code for.
A computer consists of a large array of bytes called memory, a central processing unit, and I/O devices.
The I/O devices on the Motorola system were controlled by writing and reading values from a small number of registers on the I/O chips. The serial chip was a ZILOG 8530 universal synchronous/asynchronous receiver/transmitter, or USART. What a mouthful.
Serial ports are older than computers themselves. In the early 20th century, telegraphs were being replaced by teletypes. Instead of dit’s and dah’s, you typed on a keyboard and a machine on the other end typed on the paper like a remote typewriter.
The cool thing is that all this ran on the same telegraph lines. When the telegraph key was up, it was called a space. When the key was depressed, it was called a mark. Samuel Morse, the guy who invented the telegraph in 1832, originally used a strip of paper and made marks when the remote key was depressed. Soon the telegraph operators didn’t need paper and could just listen to the sounds of the electromagnet clacking away.
The names “mark” and “space” stuck. The teletype used a rotating commutator to encode a number of marks and spaces over the wire. The first was a mark, of course, since the idle line was in space mode. This mark actually started a commutator on the remote end to begin revolving. The transmitting and receiving commutators rotated at the same speed. Spaces and marks caused a type element on the receiving teletype to be positioned to the character which was being sent. Once the receiving commutator had made a full revolution, it caused the type element to smack the ribbon and paper like a phantom typewriter, and then reset to the starting position.
When computers arrived on the scene, they used the preexisting teletypes as consoles and later as timesharing terminals.
The rate at which the marks and spaces are sent is referred to as baud rate. Later, the on and off current loop was replaced by two voltages, +10 and –10. These were defined in 1960 in the RS–232 standard and adopted by every computer manufacturer. This allowed the use of a new gadget called a modem, short for modulator/demodulator, that could send the marks and spaces over a normal, everyday telephone. Soon, there were small boxes with cups for the mouth and earpieces of a handset scattered among the glass teletypes in computer rooms and data centers around the world.
But back to my problem with the serial port on my ’147 board and the Zilog 8530 USART. On this chip was a set of registers. Each of these registers was mapped to a fixed physical memory address by the address decoding logic on the board. The book that came with the ’147 described where these were.
In the simplest form, all I/O devices have four kinds of registers: configuration, control, data, and status. The configuration register sets parameters for the device. In the case of the USART, it’s the bits per message, eight in our case, parity (none), how many stop bits (one), and the rate to send the bits, the baud rate.
The control register kicks off operations, the status register tells you how those operations are going, and the data register contains the bit being transferred. There are often more than four registers, but each will fall into one of these categories.
For example, to send a byte out the serial port, one first puts the bit in the data register, then writes the command to send it into the control register. (Some serial ICs use the write itself to start sending the byte.) The bits, starting with the least significant, will be used to set the TX bit in the serial port. Out comes the start bit, then bit 0, then bit 1, and so on. At the end there is the stop bit, which is always the opposite of the start bit.
When the whole byte has been sent, the status register tells you by setting a “transmit complete” bit. The software can sit and loop, watching that bit until it sees the transmission is complete. Then it can put another byte in the data register.
Receiving works in a similar way. When bits from a byte being sent by the terminal start showing up, the circuits on the IC do the equivalent of the commutator on the teletype, sending the bits at the baud rate interface. It shifts each bit into a receive data register. When the whole byte has arrived, an RX Done bit in the status register announces the fact. Software can loop, copying the bytes out of the receive register when the status bit says something new is in there.
Software watching the status bits is called “status driven.” Normally, we don’t want to spend all our cycles checking all the status bits for every device. So, the interrupt was invented.
Simply put, an interrupt is a subroutine call to a new routine. When the interrupt character has fully arrived, the I/O chip causes the program to save its current program counter and start fetching instructions from a prearranged location. The code at that location is called a “handler” and it removes the byte from the data register, saving it away at a convenient location.
Speaking of location, I arrived at work one day and the odd, guarded building had vanished. Poof. It was there one day and completely gone the next.
I turned to my coworker and asked, “Milan, where’d the funny warehouse go?”
“It’s not a building. It’s a floating barge. Part of Howard Hughes’ Glomar Explorer used to fetch that sunken Soviet submarine.”
“Well, I’ll be. What’s it doing here?”
“No idea, he said.”
A few days later, it reappeared!
Several years later I learned that it was the Hughes Mining Barge One, or HMB–1. Lockheed had a facility in the area, and was building a stealth ship, the Sea Shadow, for the Navy. The odd HMB–1 that could so easily disappear was how they built in secret.
Next post, I’ll tackle the SCSI driver.