![]() |
![]() |
Sure. I think I know how to fix that. I'm working to install CJL's revision "H" drivers on SIMH. I believe that driver will still crash the FORTRAN run-time unless you happen to be on an Omnibus machine (or SIMH). I believe a two line change would make it work properly on any family-of-eight machine, and possibly even on the 8/S (if you could find or create one with enough memory).
Anyway, I don't at the moment have an operational OS/8 pre-Omnibus machine to test things on, so maybe I could send you a fix to test? (Kyle has indicated he's willing to pull code if it has been tested.)
Vince
I think last time I built an OS/8 image that included serialdisk on an RX01 and tested with that.
Member of the Rhode Island Computer Museum
http://www.ricomputermuseum.org
My understanding of the Fortran run time issue is that Fortran runs with interrupts enabled. The serial ports on omnibus machines wake up so they will cause an interrupt when used by default. Fortran would catch the interrupt caused by the first character received from the serial disk server and wig out because it doesn't know what to do with it. The patch was to add the instruction to disable interrupt generation on the serial disk serial port. The RKIE (6405) needs to be executed to disable interrupt generation on a character received from the Serial disk server. The problem with using RKIE on pre Omnibus machines is that they don't know what that instruction is and it gets interpreted as the Skip if character received and read buffer command combined. Not a usual combination. If there happened to be a character in the buffer it would skip the next instruction. The way this got made sort of safe was to place a harmless constant after the RKIE. That way if it skipped it was fine on the pre-omnibus machines.
The only operating pre-omnibus machine I have does not have a second serial port so no way to test there. I guess the 8/i doesn't have a second serial port either so even if it was working...
I have the version found on github (Non sys is version D and SYS is version E) which does not have this patch and I have the version that Charles worked over (Version G) but I don't have a server for that one. Where do I go to download the version that Bob did with the server before Charles worked on it. And it sounds like Vince has Version H?
I agree with Vince that the changes I have seen will not address the issue on pre-omnibus machines. There was no provision to disable interrupt generation on a per device basis on the older machines. This makes me curious as to what Vince has in mind for a fix.
Doug Ingraham
2nd owner of Straight 8 SN1173
5 other PDP-8's including an 8/i and a DECSet 8000
SOL-20
Almost. What I believe is happening is that Fortran disables interrupts, calls the driver, then enables interrupts after the return. The issue, then, is that when the interrupts get re-enabled, there is an output completion flag set from the last character sent from the driver to the serialdisk server. This triggers and interrupt, which Fortran doesn't have handler code for. When the Fortran interrupt routine returns, the flag is still set, the interrupt recurrs, and the system is hung (except maybe for servicing other interrupts, which would still happen).
Yeah, the RKIE is just the wrong way to go about it. The "family of eight" way is to not return from the serialdisk driver with flags set. The input flag should not be troublesome, as presumably the server does not send input without being asked. The correct fix, I believe, is to remove the RKIE instruction near the beginning, and instead execute an STCF instruction prior to the return. This is the "2 line fix" I mentioned before. None of the extant serialdisk drivers do that, but it should be an easy change.The patch was to add the instruction to disable interrupt generation on the serial disk serial port. The RKIE (6405) needs to be executed to disable interrupt generation on a character received from the Serial disk server. The problem with using RKIE on pre Omnibus machines is that they don't know what that instruction is and it gets interpreted as the Skip if character received and read buffer command combined. Not a usual combination. If there happened to be a character in the buffer it would skip the next instruction. The way this got made sort of safe was to place a harmless constant after the RKIE. That way if it skipped it was fine on the pre-omnibus machines.
In principal, there's a NOP later after an ISZ, where that inline constant could go, which would likely save a word. No too important as there are several words to spare at the moment.
So maybe Michael's PDP-12 is the place to test it, though he won't see the problem if his serialdisk serial port is on the Omnibus. (Or maybe the DECmate?)The only operating pre-omnibus machine I have does not have a second serial port so no way to test there. I guess the 8/i doesn't have a second serial port either so even if it was working...
That's the problem I'm working on, that the new code isn't generally available. Kyle is amenable to taking it, as long as it is tested and I can generate a github pull request with the various versions in it.I have the version found on github (Non sys is version D and SYS is version E) which does not have this patch and I have the version that Charles worked over (Version G) but I don't have a server for that one. Where do I go to download the version that Bob did with the server before Charles worked on it. And it sounds like Vince has Version H?
Charles' changes for Version H vs version G are pretty trivial. As usual, he couldn't leave the comments alone, but the actual code change is I think three lines to save a word, by having an output routine return the value that was output, rather than clearing the AC.
Hopefully I was clear above?I agree with Vince that the changes I have seen will not address the issue on pre-omnibus machines. There was no provision to disable interrupt generation on a per device basis on the older machines. This makes me curious as to what Vince has in mind for a fix.
Vince
Correct, in as far as what the FORTRAN runtime system does. When calling OS/8 drivers, interrupts needs to be off, since the drivers are written with that assumption.
But I don't get it. The serial disk driver uses a KL8E or KL8JA, right? And it's not interrupt driven in itself, I would assume (since OS/8 is not interrupt driven at all).
So I fail to understand how the serial disk could generate any interrupts. The KL8E and KL8JA do not generate any interrupts, unless you explicitly turn that on. Why would anything do that?
Or is this when used with some other serial controller, which always generates interrupts?
Mostly it has been used to date with KL8E or KL8J, or cards (or software) that emulate them.
You are incorrect, in that these cards *do* default to a mode where the flag raises an interrupt request when it is set. So if interrupts become enabled, there will be one. That's what the RKIE kludge was about -- doing an RKIE instruction with AC clear, on controllers that support it, switches the "flag generates interrupt request" behavior off.
Arguably, that's a sub-optimal default. However, older PDP-8's and their serial controllers don't implement RKIE or any other method of changing the behavior, and their default was "flag implies interrupt request" (else there's no way to get one). So this default means that the Omnibus serial devices default to the behavior of their predecessors.
Which is all fine, if we don't use interrupts, or if our interrupt handler knows what to do for every device we use. When we use OS/8 to control devices Fortran's interrupt system knows nothing about, we need to be sure we don't leave flags/requests around that Fortran will be stymied by.
Vince
Ok I understand. Here is the SENDC code from the CJL version I have.The RTLS sends the character to the server. The RTSF loop waits until all bits have been sent. The flag is set at this point and when you return the Fortran runtime will enable interrupts and instantly an interrupt will occur. Since Fortran does not know what to do with an interrupt from device code 41 it fails to clear the interrupt and hangs. The solution is to clear the flag by adding an RTCF instruction before the return.Code:SENDC, .-. /TRANSMIT A CHARACTER ROUTINE. RTLS /SEND THE CHARACTER IN THE AC. RTSF /SEND FLAG UP? JMP .-1 /NO, WAIT FOR IT. JMP I SENDC /YES, RETURN TO CALLER WITH AC INTACT.For the receive operation the current code isCode:SENDC, .-. /TRANSMIT A CHARACTER ROUTINE. RTLS /SEND THE CHARACTER IN THE AC. RTSF /SEND FLAG UP? JMP .-1 /NO, WAIT FOR IT. RTCF /CLEAR THE FLAG JMP I SENDC /YES, RETURN TO CALLER WITH AC INTACT.The seemingly obvious way to fix this is to just add an additional RKCC before the return (JMP I GETNUM). Looks like this:Code:GETNUM, .-. /RECEIVE 12-BIT WORD FROM TWO CHARACTERS ROUTINE. RKCC /CLEAR THE RECEIVE FLAG, AC. RKSF /RECEIVE FLAG UP? JMP .-1 /NO, WAIT FOR IT. RKRB /YES, READ IN FIRST SIXBIT CHARACTER. CLL RTL;RTL;RTL /MOVE UP TO HIGH-ORDER BITS. RKSF /RECEIVE FLAG UP? JMP .-1 /NO, WAIT FOR IT. RKRS /.OR. SECOND SIXBIT CHARACTER INTO AC. JMP I GETNUM /RETURN TO CALLER.The problem with this is that it doesn't work because while the RKCC clears the flag it also clears the AC. To add this instruction at this point would require saving the AC, Clear the flag with the RKCC and then reloading the value. Not a good use of the limited code space if we can help it. For our purposes the best place to clear both of these flags is right before the return from the handler. Unfortunately, there are two return points in most handlers. One is the regular return and the other is the control C return. The control C return is the one that would confuse you because if you control C out of the handler and leave the flags set, everything will work fine until you run a Fortran program. Then Fortran will hang as soon as it enables the interrupts. Lets just rewrite the GETNUM routine to eliminate the issue.Code:GETNUM, .-. /RECEIVE 12-BIT WORD FROM TWO CHARACTERS ROUTINE. RKCC /CLEAR THE RECEIVE FLAG, AC. RKSF /RECEIVE FLAG UP? JMP .-1 /NO, WAIT FOR IT. RKRB /YES, READ IN FIRST SIXBIT CHARACTER. CLL RTL;RTL;RTL /MOVE UP TO HIGH-ORDER BITS. RKSF /RECEIVE FLAG UP? JMP .-1 /NO, WAIT FOR IT. RKRS /.OR. SECOND SIXBIT CHARACTER INTO AC. RKCC /CLEAR FLAG SO FORTRAN DOESN'T HANG JMP I GETNUM /RETURN TO CALLER.The original is 13 words long and the new version is 14 words. We don't need to clear the flag on GETC entry because it must already be clear. The only problem now is the assumption that the flag was initially clear. It should be because when you start the machine from the front panel one thing that happens is all devices are supposed to be reset. And since GETC always exits with it clear it should stay that way unless the server sends something. The one other place that could leave the flag set would be the serial disk boot code if you are booting from it. And I just checked the boot code in the handler and it does leave the receive flag set. We could change the boot but it would be easier to just replace the RKIE on handler entry with RKCC as sort of an initializer. So what did we overlook?Code:GETC, .-. /GET A CHARACTER FROM THE SERVER RKSF /CHECK THE FLAG AND SKIP IF SET JMP .-1 /WAIT FOR THE FLAG RKRB /CLEAR AC, READ THE CHARACTER AND CLEAR THE FLAG JMP I GETC /RETURN GETNUM, .-. /RECEIVE 12-BIT WORD FROM TWO CHARACTERS ROUTINE. JMS GETC /GET THE FIRST 6 BITS CLL RTL;RTL;RTL /SHIFT LEFT 6 BITS DCA SENDC /USE SENDC RETURN ADDRESS AS A TEMP JMS GETC /GET THE LOWER 6 BITS TAD SENDC /COMBINE THE TWO FRAMES JMP I GETNUM /RETURN TO CALLER.
Doug Ingraham
2nd owner of Straight 8 SN1173
5 other PDP-8's including an 8/i and a DECSet 8000
SOL-20
Bookmarks