Home

IBM 5150  -  10/27/82 BIOS  -  Problem of less than 4 banks of RAM


IBM documentation on the IBM 5150 does not indicate a requirement for 4 banks of motherboard RAM.  However, with the 10/27/82 revision BIOS fitted to either the 16KB-64KB or 64KB-256KB versions of the 5150 motherboard, it will be found that 4 banks are required, else problems result.

The problems are the result of two software bugs in the 10/27/82 revision BIOS.
The first bug affects only the 64KB-256KB version of the 5150 motherboard.
The second bug affects both the 16KB-64KB and 64KB-256KB versions of the 5150 motherboard.




Bug #1

This is a bug in the 10/27/82 revision of the 5150 BIOS, and this particular bug affects only the 64KB-256KB version of the 5150 motherboard.

The bug appears to come about because much code was copied from the early BIOS, as used on 16KB-64KB motherboards (up to 4 banks of 16 KB RAM), and inadequate testing done to verify that the code worked fully (repeat: fully) on the 64KB-256KB motherboard (up to 4 banks of 64 KB RAM).


Reference

BIOS source listing in the APR84 edition of the 5150 Technical Reference


Symptoms

When less than 4 banks of motherboard RAM are indicated, the bug results in the BIOS reporting much less RAM than it should.

Motherboard banks
indicated via SW1
RAM in
expansion cards
SW2
setting
RAM total
reported by BIOS
     Comment
0   (64 KB)   N/A   64 KB 16 KB  BAD - Should be 64 KB      (1 x 64 KB bank)
0/1   (128 KB) N/A 128 KB 32 KB  BAD - Should be 128 KB    (2 x 64 KB bank)
0/1/2   (192 KB) N/A 192 KB 48 KB  BAD - Should be 192 KB    (3 x 64 KB bank)
0/1/2/3   (256 KB)   0 KB 256 KB 256 KB  GOOD         (4 x 64 KB bank)
0/1/2/3   (256 KB) 64 KB 320 KB 320 KB  GOOD         ([4 x 64 KB bank] + 64 KB)
0/1/2/3   (256 KB) 128 KB 384 KB 384 KB  GOOD         ([4 x 64 KB bank] + 128 KB)

When this problem happens, the amount of BIOS reported RAM may be too little for certain versions of DOS.  See here.


Where did I get the 'RAM total reported by BIOS' figures above?

The 5150 BIOS/POST stores the total amount of RAM (in KB) that it detected into the BIOS Data Area (BDA), specifically the word (little endian) at 0040:0013.
One way to read that amount is to:
1.  Get into BASIC by removing any hard drive, and then boot without a boot floppy, then
2.  In BASIC, enter the following:
   def seg = &h40
   print peek(&h14)*256 + peek(&h13)


Where in the code is the bug?

The block of code causing the problem is on page 5-42 of the reference, specifically lines 934 to 951.  That block calculates the total KB amount of RAM (motherboard + expansion cards) and then stores the amount in the BDA.

You can see that the block I'm referring to is divided in to 2 sections: "DETERMINE RAM SIZE ON PLANAR BOARD" and "DETERMINE I0 CHANNEL RAM SIZE".  Those descriptions are correct for a 16KB-64KB motherboard, but not a 64KB-256KB motherboard.

DETERMINE RAM SIZE ON PLANAR BOARD

Lines 935 to 941.  This section of the block examines switches 3 and 4 on SW1.  Irrespective of whether the 10/27/82 BIOS is on a 16KB-64KB motherboard or on a 64KB-256KB motherboard, the output of that section is always the same:
SW1-3 on / SW1-4 on (i.e.  bank 0) - results in register BX containing 16 (0010h).
SW1-3 off / SW1-4 on (i.e.  banks 0/1) - results in register BX containing 32 (0020h).
SW1-3 on / SW1-4 off (i.e.  banks 0/1/2) - results in register BX containing 48 (0030h).
SW1-3 off / SW1-4 off (i.e.  banks 0/1/2/3) - results in register BX containing 64 (0040h).

DETERMINE I0 CHANNEL RAM SIZE

Lines 945 to 951.

The first thing that this bit of code does (at line 945) is fetches the "IO_RAM_SIZE" value was calculated (based on SW-2 setting) and stored earlier (page 3-37).  IO_RAM_SIZE contains the amount of RAM past 64 KB.  On a 16KB-64KB motherboard, that corresponds to the amount of IO RAM (RAM on IO expansion cards), and so on that motherboard, "IO_RAM_SIZE" is an accurate description.  But on a 64KB-256KB motherboard, "IO_RAM_SIZE" is an incorrect description.  It is best to think of "IO_RAM_SIZE" as RAM past 64 KB.

Putting it altogether (lines 935 to 951), we end up with:

Motherboard banks
indicated via SW1
RAM in
expansion cards
SW2
setting
BX
register
BX = 0040h ? IO_RAM_SIZE
(KB RAM past 64)
 Calculated RAM total (MEMORY_SIZE)
0   (64 KB)   N/A   64 KB 16  (0010h) No not relevant  16 + 0 = 16 KB        ( BX + 0 , because BX not 0040h )
0/1   (128 KB) N/A 128 KB 32  (0020h) No not relevant  32 + 0 = 32 KB        ( BX + 0 , because BX not 0040h )
0/1/2   (192 KB) N/A 192 KB 48  (0030h) No not relevant  48 + 0 = 48 KB        ( BX + 0 , because BX not 0040h )
0/1/2/3   (256 KB)   0 KB 256 KB 64  (0040h) Yes 192  (00C0h)  64 + 192 = 256 KB        ( BX + IO_RAM_SIZE )
0/1/2/3   (256 KB)  64 KB 320 KB 64  (0040h) Yes 256  (0100h)  64 + 256 = 320 KB        ( BX + IO_RAM_SIZE )
0/1/2/3   (256 KB) 128 KB 384 KB 64  (0040h) Yes 320  (0140h)  64 + 320 = 384 KB        ( BX + IO_RAM_SIZE )





Bug #2

This is a software bug in the 10/27/82 revision of the 5150 BIOS.
This particular bug affects both the 16KB-64KB 5150 motherboard (if the 10/27/82 BIOS is fitted) and the 64KB-256KB 5150 motherboard.


Reference

BIOS source listing in the APR84 edition of the 5150 Technical Reference


Symptoms

Mostly, when less than 4 banks of motherboard RAM are indicated via SW1/SW2, a 201 error (RAM error) is seen on screen.

Why did I use "mostly"?
Here is an example.  64KB-256KB motherboard.
SW1 and SW2 set for 1 bank of RAM only (64K), and only 1 bank is physically fitted - 201 error seen.
SW1 and SW2 set for 1 bank of RAM only (64K), but 4 banks are physically fitted - 201 error not seen.


Why?

Because of a software bug, if less than 4 banks of motherboard RAM are indicated via SW1/SW2, then the portion of the POST that does a data test of the RAM thinks that there is a lot more RAM fitted than indicated by SW1/SW2.
Here are some examples for a 64KB-256KB motherboard:

Motherboard banks
indicated via SW1
RAM in
expansion cards
SW2
setting
RAM test routine thinks
this much RAM exists
     Comment
0   (64 KB)   N/A   64 KB 192 KB  BAD  -  128K more than actually exists
0/1   (128 KB) N/A 128 KB 384 KB  BAD  -  256K more than actually exists
0/1/2   (192 KB) N/A 192 KB 448 KB  BAD  -  256K more than actually exists
0/1/2/3   (256 KB)   0 KB 256 KB 256 KB  GOOD
0/1/2/3   (256 KB) 64 KB 320 KB 320 KB  GOOD
0/1/2/3   (256 KB) 128 KB 384 KB 384 KB  GOOD


Where in the code is the bug?

The block of code causing the problem is on page 5-37 of the reference, specifically lines 525 to 539, which is the majority of the section named "DETERMINE I0 CHANNEL RAM SIZE".  The block is calculating something known as "IO_RAM_SIZE", and as explained in BUG #1, IO_RAM_SIZE is the amount of RAM past 64 KB.

This block is a modified form of the one in the earlier BIOS.  It is modified because this BIOS now reads switches #1 to #5 on SW2.  The earlier revisions of BIOS only went as high as switch #4.  In modifying the code, the programmer has introduced a bug.  The bug results in wrong values of IO_RAM_SIZE being calculated when less than 4 banks of motherboard RAM are indicated via SW1/SW2.

Here are some examples for a 64KB-256KB motherboard:

Motherboard banks
indicated via SW1
RAM in
expansion cards
SW2
setting
IO_RAM_SIZE
(KB RAM past 64)
RAM test routine thinks
this much RAM exists
     Comment
0   (64 KB)   N/A   64 KB 128 KB 128 + 64 = 192 KB  BAD
0/1   (128 KB) N/A 128 KB 320 KB 320 + 64 = 384 KB  BAD
0/1/2   (192 KB) N/A 192 KB 384 KB 384 + 64 = 448 KB  BAD
0/1/2/3   (256 KB)   0 KB 256 KB 192 KB 192 + 64 = 256 KB  GOOD
0/1/2/3   (256 KB) 64 KB 320 KB 256 KB 256 + 64 = 320 KB  GOOD
0/1/2/3   (256 KB) 128 KB 384 KB 320 KB 320 + 64 = 384 KB  GOOD

By the way.  It is relatively easy for you to see the IO_RAM_SIZE figure for yourself.  That is bacause the 5150 BIOS/POST stores the IO_RAM_SIZE figure that it calculated into the BIOS Data Area (BDA), specifically the word (little endian) at 0040:0015.
One way to read that amount is to:
1.  Get into BASIC by removing any hard drive, and then boot without a boot floppy, then
2.  In BASIC, enter the following:
   def seg = &h40
   print peek(&h16)*256 + peek(&h15)


Where did the programmer go wrong?

If you examine the block of code (lines 525 to 539) carefully, you will discover that the block, by accident no doubt, requires that the upper nibble in register AH be zero before the block is executed.
A non-zero nibble corrupts the calculated value of IO_RAM_SIZE

So what's before the block that affects the upper nibble in register AH?
Another block, lines 511 to 521, in which register AH will end up as:

Motherboard banks
indicated via SW1
AH
register
Non-zero
upper nibble?
0   64 (40h) Yes
0/1 128 (80h) Yes
0/1/2 192 (C0h) Yes
0/1/2/3     0 (00h) No