Heading:
Chained Ethernet Input
Page Numbers: Yes X: 527 Y: 10.5"
Private Data Stamp: No X: 6.75" Y: 0.40"
XEROX
BUSINESS SYSTEMS
Systems Development Department
To:Boggs, Taft, Hupp, ShochDate:January 6, 1979

From:
Hal Murray Org:SDD/SD System Architecture

Subject:
Chained Ethernet Input Filed:[IVy]<Portola>ChainedEther.bravo

I have modified the Alto Ethernet microcode to include a simple form of input chaining. It will not catch back to back packets, but it will restart the receiver without waiting for an interrupt to get processed. The sources are stored with the rest of the microcode used by the Alto Gateway in [IVY]<Portola>GatewayMC.dm. The Alto Gateway program tries to keep four buffers ready. Two wasn’t enough, and four seems to be plenty, but I didn’t study the problem carefully.
The implementation adds a 10th word to the Ethernet control block in low core. That is location 611 for the normal Ethernet board. If this chain word in not zero, it is assumed to be a pointer to an Input Control Block. I’ll call it the main chain word to distinguish it from the chain word in an Input Control Block. For simplicity, an Input Control Block has the exact same format as the Main Control Block, even though some of the fields in either block are not used.
The input count&pointer and end count in the Main Control Block are not used. The output count&pointer as well as the retransmission mask and host number of Input Control Blocks are not used. When needed, the host number is always loaded from the the Main Control Block.
Whenever a StartIO[3] is issued, or something horrible happens, the microcode will post in the main post location and stop. Horrible things include an odd chain word, a zero length input buffer or output buffer, or an input pointer that is 0.
Whenever a StartIO[2] or StartIO[1] is issued when the microcode was resting, and whenever the microcode finishes a normal input or output, it looks for more to do. "more" includes both input and output. You can think of this as output-under-input as well as input under output. If there is nothing to do, then the microcode stops without posting.
When the microcode is looking for things to do, it first looks for output. If the output pointer of the Main Control Block is not zero, it starts sending that packet. The normal in under out mechanisim is still active, but it tests the main chain word rather than the input pointer. If there is nothing to send, then the main chain word is tested. If it is non zero, the the receiver is started, and the packet will be read into the buffer specified by the input count and pointer of the first Input Control Block.

Whenever the microcode finishes sending a packet, it zeros the output pointer so that it won’t send the same packet again, and posts into the Main Control Block. Whenever it finishes receiving a packet, it posts into the current Input Control Block, and advances the main chain word. In both cases, the microcode then looks for more work to do. If an abort happens, the normal information is posted into the main post location and the microcode goes to sleep. (Posting includes generating wakeups on the appropiate channels.)
A StartIO[1, 2 or 3] during actual sending or receiving is considered as an abort just like in the normal microcode. A StartIO[1 or 2] while waiting for input (including input under output) just causes the microcode to go look for something to do again. This is useful when trying to start sending while the microcode is waiting for input. In practice, very few packets are clobbered by StartIOs at an inopportune time.
To send a buffer, first clear the post location and load location, setup the count, and finally setup the pointer. Be careful to store the output pointer last, or the microcode may try to start sending things too soon if an input packet arrives at the wrong time. If input is pouring in, do nothing more -- the microcode will start sending the packet when it finishes reading the current packet. (Remember that the microcode can change the main chain word while you are looking to see if something is pouring in.) Next, look at the retransmission mask to see if the output has already been started because a packet arrived while you were chasing pointers to see if any input was pouring in. If the microcode appears to be idle (no input buffers setup, or the first word of the current input buffer is still zero, and the retransmission mask is still 0) then issue a StartIO[1 or 2] to poke the microcode.
To add a buffer to the input chain, first setup a control block with the pointer and length and a 0 chain word and a 0 post location. Append the new Input Control Block to the end of your chain. The driver needs maintain a pointer to last Input Control Block for this purpose. Now, if the main chain word is 0, go back and see if your new Input Control Block has been posted. If not, then the microcode ran out of buffers before it found your new one, so store a pointer to the new Input Control Block in the main chain word and issue a StartIO[1 or 2]. (You may want to check to see if there is an output buffer setup before doing the StartIO. If there is output in progress, you may clobber it.) If it has been posted alteady, then the microcode saw your new buffer, and has already placed a packet into it, and chained past it before you could look at the main chain word.
When an interrupt happens, you have to check both the post word in the Main Control Block, and the post word in the first Input Control Block on your chain. Again, the driver needs maintain a pointer to first Input Control Block for this purpose. Remember that the interrupt system only stacks one extra interrupt, so you have to process all the interrupts that might have been merged into one. (I don’t think order is too important, but some details of your interrupt routine might make it critical. The only complication that I know of is that the information in the main post location may be lost if something horrible happened and you restart the microcode because it ran out of buffers.) The only reasonable microcode status in the main post location are output done, load overflow, and reset. If the first Input Control Block on your chain has been posted, process it, and check the next one. The only reasonable microcode status in the post location of an Input Control Block are input done and input buffer overrun. Horrible things all post the zero length buffer microcode status code into the main post word, but of course. If you want to reover from one of these, you will have to kick the microcode to get it started again.