[comp.os.minix] Request for advice on PS/2 problems

ast@cs.vu.nl (Andy Tanenbaum) (01/23/89)

Steve Ackerman has reported getting MINIX to boot on the PS/2 Model 80.
Good work!  However, we are not really done yet.  I have to figure out
how to deal with level-triggered interrupts in a reasonable way.  This
message solicits suggestions.  Please post them, since 10K heads are
better than 1.

MINIX, like all other message passing operating systems, does not do much
in its interrupt routines.  It just sends a message and returns from the
interrupt.  This means that after a floppy disk interrupt, the interrupt
line would normally still be asserted.  However, to shut off the 8259A
interrupt controller, on line 1888, we order it to shut up.  On the PS/2
this doesn't work.  We have to actually talk to the device.  It is
probably unwise to do this inside the interupt() function.  This means
we have to move line 1888 to each device driver and do it there.  Unpleasant
but possible.

However, things are worse than this.  If we delete line 1888 and move it
to the device drivers, when the interrupt routine is finished, we will get
another interrupt.  To prevent this, Steve diddled the 8259A's interrupt
mask around line 1888.  Double ugly.

My question is: does anybody see a better and cleaner way to do this?
I don't especially want the code around line 1888 having to figure out
which of the 8259A's to diddle, and which bit, etc.  For the floppy it
may not be too bad, but for serial I/O, networking, etc, it will make
things more complicated and error prone in a sensitive area.  On the other
hand, I don't want a major redesign of things.  I think the original
design is fairly simple and don't want to muck it up because of the way
the PS/2 does things.) I'd also like to minimize the amount of code of the sort

if (ps)				/* Models 25 - 80 */
if (mca) ...			/* microchannel architectures only */
if (ps && mca == FALSE) ...	/* Models 25 and 30 */
etc.

Hardware types, get out your thinking caps.

Another point, I am still trying to figure out exactly how to tell if 
a machine is (1) PS/2 and (2) Microchannel.  Several people have pointed
out that INT 15 is supposed to tell you, but I can't find that in my
(PC) BIOS manual.  Maybe it is something new.  Could some kind soul please
write a little piece of code that can be added to klib88.s making the
call to int15, and then write the C code for using this call to set the
variables ps and mca in such a way that it works on PC, XT, AT, and PS/2
(preferably without including a complete expert system in there).  Thanks.

Andy Tanenbaum (ast@cs.vu.nl)

steve@basser.oz (Stephen Russell) (01/25/89)

In article <1944@ast.cs.vu.nl> ast@cs.vu.nl (Andy Tanenbaum) writes:
>
>[ ... ]  I think the original
>design is fairly simple and don't want to muck it up because of the way
>the PS/2 does things.)

This won't be the first time that a simple system had to be abandoned
because of badly-designed hardware :-)

>Another point, I am still trying to figure out exactly how to tell if 
>a machine is (1) PS/2 and (2) Microchannel.  Several people have pointed
>out that INT 15 is supposed to tell you,

Only ref I have is in Thom Hogan's "The Programmer's PC Sourcebook", pp234.
INT 0x15, function AH=0xC0 returns a pointer in ES:BX to a "System
Descriptor Table". The layout is as follows:

	Offset	Length	Description		Value

	0	Word	Size of table in bytes	>= 8
	2	Byte	Model byte		See below
	3	Byte	Submodel byte		"
	4	Byte	BIOS Revision level	00 = first release
	5	Byte	Features		bit 7 HD BIOS uses DMA 3
						bit 6 2nd interrupt chip present
						bit 5 RTC present
						bit 4 keyboard intercept called
						bit 3 wait for ext event called
						bit 2 extended BIOS area alloc'd
						bit 1 PS/2-type I/O channel
						bit 0 (Reserved)

The rest is reserved. The interesting things are the model bytes and bit 1
of byte 5. Note: According to Hogan, this stuff applies to AT's after
1985 Nov 15, XTs after 1986 Jan 10, all XT286s, Convertibles and PS/2s.
His ref is IBM PS/2 and PC BIOS Interface Tech Ref, pp 2-94 to 2-96.

On page 197 of Hogan, the model number bytes are described as follows:

	Model Byte  Submodel Revision BIOS Version  Machine

	    FF        --        --        All	    IBM PC
	    FE	      --        --      8 Nov 82    PC/XT and Portable PC
	    FD        --        --        All       PCjr
	    FC        --        --     10 Jan 84    AT
		      00        01     10 Jun 85    AT
		      01        00     15 Nov 85    AT
		      04	00     Initial      PS/2 Model 50
		      05        00     Initial      PS/2 Model 60
		      02        00       All        PC/XT286
	    FB	      00	01     10 Jan 86    XT
		      00        02      9 May 86    XT
	    FA        00	00      2 Aug 86    PS/2 Model 30
	    F9        00	00     13 Aug 85    PC Convertible
	    F8	      00	00      Initial     PS/2 Model 80
		      01	00	Initial     PS/2 Model 80
	    FE	      NA	NA		    Compaq DeskPro
	    2D	      NA	NA		    Compaq Portable
	    9A	      NA	NA		    Compaq Portable Plus
	    4B	      NA	NA		    MegaBIOS ROM
	    B6	      NA	NA		    HP110 Portable
	
The machine model byte can also be found at address F000:FFFE. Ref:
PS/2 and PC BIOS Tech Ref, page 4-18.

So, the strategy to find the machine might be something like this:

- Check the model byte at F000:FFFE.
- If it's F[BDEF], then it's a PC, XT or Jr.
- If it's F8 or FA, it's a PS/2.
- If it's FC, could be an AT, XT286 or PS/2 Model 30/50. Early model
AT's will not support INT 0x15:0xC0 (carry set on return?). The rest
can be differentiated by the submodel/revision bytes.
- If it's none of the above, assume a PC clone, and hope for the best!

- For PS/2 machines, check bit 1 in byte +5 in configuration block for
PS/2 style I/O channels.

Now I don't have enough machines around here to test this out, but
others on the net may be able to check the details for their machine.
Of course, who knows what the clone makers have done. Fortunately, there
aren't a lot of PS/2 MCA clones (yet), but let's hope they get the
above details right.  One worry: why are there 2 model 80's for F8?
Mistake in Hogan's table?

gaz@apollo.COM (Gary Zaidenweber) (01/25/89)

From article <1944@ast.cs.vu.nl>, by ast@cs.vu.nl (Andy Tanenbaum):
> Steve Ackerman has reported getting MINIX to boot on the PS/2 Model 80.
> Good work!  However, we are not really done yet.  I have to figure out
> how to deal with level-triggered interrupts in a reasonable way.  This
> message solicits suggestions.  Please post them, since 10K heads are
> better than 1.
> 
> MINIX, like all other message passing operating systems, does not do much
> in its interrupt routines.  It just sends a message and returns from the
> interrupt.  This means that after a floppy disk interrupt, the interrupt
> line would normally still be asserted.  However, to shut off the 8259A
> interrupt controller, on line 1888, we order it to shut up.  On the PS/2
> this doesn't work.  We have to actually talk to the device.  It is
> probably unwise to do this inside the interupt() function.  This means
> we have to move line 1888 to each device driver and do it there.  Unpleasant
> but possible.

In my opinion, level-triggered interrupts are far preferable to edge-triggered
ones. One approach might be to rethink the definition of "does not do much in
its interrupt routines" and the explicit and implicit content of messages. I'm
sorry that I haven't looked at the code, but I have both designed and coded
drivers for many types of network devices in a multitasking OS.
> 
> However, things are worse than this.  If we delete line 1888 and move it
> to the device drivers, when the interrupt routine is finished, we will get
> another interrupt.  To prevent this, Steve diddled the 8259A's interrupt
> mask around line 1888.  Double ugly.

Again, my opinion, the interrupt dispatcher should be returned to by the
interrupt routine after its execution and the dispatcher will diddle such
machine-dependent hardware as the 8259A. It knows which routine was dispatched.
Well-designed controllers should be able to queue level-triggered interrupts.
> 
> My question is: does anybody see a better and cleaner way to do this?
> I don't especially want the code around line 1888 having to figure out
> which of the 8259A's to diddle, and which bit, etc.  For the floppy it
> may not be too bad, but for serial I/O, networking, etc, it will make
> things more complicated and error prone in a sensitive area.  On the other
> hand, I don't want a major redesign of things.  I think the original
> design is fairly simple and don't want to muck it up because of the way
> the PS/2 does things.) I'd also like to minimize the amount of code of the sort
My above suggestions, unfortunately, do add a bit of complexity with the payoff
of "nearly infinite :-)" flexibility.
> 
> if (ps)				/* Models 25 - 80 */
> if (mca) ...			/* microchannel architectures only */
> if (ps && mca == FALSE) ...	/* Models 25 and 30 */
> etc.
> 
> Hardware types, get out your thinking caps.
> 
> Another point, I am still trying to figure out exactly how to tell if 
> a machine is (1) PS/2 and (2) Microchannel.  Several people have pointed
> out that INT 15 is supposed to tell you, but I can't find that in my
> (PC) BIOS manual.  Maybe it is something new.  Could some kind soul please
> write a little piece of code that can be added to klib88.s making the
> call to int15, and then write the C code for using this call to set the
> variables ps and mca in such a way that it works on PC, XT, AT, and PS/2
> (preferably without including a complete expert system in there).  Thanks.
> 
> Andy Tanenbaum (ast@cs.vu.nl)
-- 
Gary Zaidenweber        |   It's nice to know that if someone gets
UUCP:   umix!apollo!gaz |   caught shredding the constitution, that
ARPA:   gaz@apollo.COM  |   you can at least charge him with littering.
AT&T:   +1 508 256 6600 |    -- Jay Leno