Saturday, September 25, 2021

VAXstation 1 Software Install - Part 3 - The System Control Block


  So now I can print strings and data on the console. Next step was to deal with exceptions and interrupts. If I'm writing this program, I can pretty much guarantee there will be exceptions. And if I get the devices working, there will definitely be interrupts. These are both handled by the System Control Block. The SCB is two pages of addresses (AKA vectors) to the routines that handle exceptions and interrupts. The first 128 of them are for exceptions. I set all of them to point to a routine that will dump the top 10 longwords on the stack and halt. If something goes wrong, that'll be a good start figuring out what happened. The SCB address is returned from internal processor register ^X11. 



        mfpr    #^x11,r7            ;move scb addr to r7

        movab   ^X200(r7),r7        ;move addr of scb+512 to r7
        movzbl  #^X7f,r9            ;put 127 decimal  in r9

scbloop:
        moval   xfcme,-(r7)
        sobgeq  r9,scbloop          ;...in the SCB


  And here's the routine the exceptions will trap to. Dump is a routine that translate the bytes to hex and prints them out as a string.

xfcme:
        movl    sp,r0
        dump    #40,(r0)
        halt


  To test the exception handling routine, I needed to cause one and see if my routine executed. The easiest most reliable way to cause an exception is to execute the XFC (eXtended Function Call) instruction.  This is an opcode reserved by DIgital for customer use (and that's me!). XFC 's exception vector is at offset ^X14 in the SCB. Since I set 'em all pointing to my routine, I got that covered. I wrote a program to test it and loaded it to run.  When it ran, I got my routine called, so it's a success.

  Here's the test program, It's not much of a program, being one instruction long and all...

        xfc

  Here's a test run

>>>B XQA0
ATTEMPTING BOOTSTRAP

5F70000000001F04FFFF00A06850E2FF0C204002FFFF0000000000000000000000500000FFBF0080

00008FE4 06

  Above is the result - it booted, executed the XFC instruction, trapped to my routine. It printed out 10 longwords worth of bytes, and then halted. The last line shows the halt address, and the halt cause, 06, which is , program executed a HALT instruction in kernel mode.

  Ok, we've got exceptions handled, now on to the second page of the SCB, which handles interrupts.

  The next 128 vectors (the second page) are for device interrupts.  In this particular project, only one device will be interrupting - the DEQNA. The RQDX3 can interrupt, but they aren't required - I'll treat it like it's a programmed IO device. The DEQNA doesn't have its vector set by jumpers on the card, like most DEC peripherals. YOu can set it by writing to a device register. It defaults to 774. Since there's only one device interrupting in this application, I put its interrupt  routine address in all 128 addresses in the interrupt part of the SCB. That way, it works no matter what the card is set to use. This is lazy, and I admit, funny things will happen if any other card interrupts, but, it seems to work fine. I filled them in in like wise to the way I did the first page

  Here, the routine bing is the interrupt service routine - the name bing was chosen as a tribute to the RSX interrupt method as described in "The Hamster Theory of RSX". If you haven't read it, stop right now and do a search for it. I'd provide a link  to it, but the author doesn't like links to his pages. You'll never find a better explanation of how an OS works than this one. Be sure and read the version that has pictures.  Anyway....

        mfpr    #^x11,r7        ;move scb addr to r7
        movab   ^X200(r7),r7    ;move addr of scb+512 to r7
        movzbl  #^X7f,r9        ;put 127 decimal  in r9

sc2loop:
        moval   bing,(r7)+
        sobgeq  r9,sc2loop

        mess    preXFC
        xfc
        mess    postXFC

  OK, the SCB is all set up. One last detail regarding interrupts, and it took me a few days to puzzle it out. I couldn't understand why the DEQNA wasn't interrupting when it received a packet. I finally realized that the card was interrupting at IPL4. The MicroVAX 1 sets the IPL to 31 after a power on, so the IPL 4 interrupt was getting ignored. I set the IPL to 1, and now the DEQNA interrupts could be acknowledged. The IPL is read and written from internal processor register ^X12.


        mtpr    #1,#^X12        ;set it to 1, so DEQNA can interrupt

  Alright that's it for the SCB, exceptions and interrupts. Next, part 4 will deal with doing DEQNA IO. 

No comments:

Post a Comment

Comments?