The following article is compiled from postings made to emutos-devel by
Christian Zietz, and used with his permission.


Memory bank detection on the ST and STe
=======================================
First, keep in mind that I figured this out from looking at the code
and testing on my ST.  Jean-François del Nero helped out a lot by doing
the STe tests, since I don't own an STe.

Memory detection works individually for each bank by telling the MMU to
assume 2 MB of RAM in that bank and then testing where patterns repeat.
Now, the ST and the STE MMU differ on how they decode memory addresses.
Thus, these repetitions occur at different memory locations.

DRAM is addressed by rows and columns, so the MMU decodes a RAM address
(21 bits, A20-A0, to address a maximum of 2 MB per bank) into row and
column addresses.  As the RAM data bus is 16 bits wide, A0 doesn't need
to be decoded.  In fact it's not even on the address bus.  So we use 20
bits, 10 for row and 10 for column.

ST memory bank detection
------------------------
The address that is checked by the detection algorithm for a 512 kByte
bank is 0x408 = 0 0000 0000 0100 0000 1000b.  The ST MMU (when set to
2MB) does the following decode of that address (Rx and Cx are row and
column address lines respectively):

0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
C C C C C C C C C C R R R R R R R R R R X
9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X

Now a 512 kByte bank does not use row and column address lines 9, so you
can see that, if we have set the memory controller for a 2MB bank but
really have a 512 kByte bank, 0x408 will map to 0x008.  This is exploited
by the detection algorithm.

STe memory bank detection
-------------------------
The address that is checked by the detection algorithm for a 512 kByte
bank is 0x80008 = 0 1000 0000 0000 0000 1000b.  It is decoded differently
though:

0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
C R C R C R C R C R C R C R C R C R C R X
9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X

Again, C9 and R9 don't exist in a 512 kByte bank, hence in an STe
0x80008 will map to 0x00008 during memory detection.



Writing memory detection code that works on STs and STes
========================================================
There are five possible different standard memory setups; each has a
different wraparound address (always assuming that the memory controller
has been set for a 2MB bank):
1. STe w/128kB bank (if they exist): wraparound @ 0x40008
2. ST w/128kB bank: wraparound @ 0x208
3. STe w/512kB bank: wraparound @ 0x80008
   Note that this will also wraparound on an ST w/128kB bank, so we
   must test for the 128KB bank first
4. ST w/512kB bank: wraparound @ 0x408
5. ST or STe w/2MB bank: no wraparound

Here are the details.  Don't forget: the wraparound occurs because the
high order bits of row and column addresses are ignored on smaller banks.
On a 512kB bank, bits R9/C9 are ignored; on a 128kB bank, bits R8-R9 and
C8-C9 are ignored.

Address 0x208
-------------
ST => will correctly wrap around at R8 when 128 kByte are installed
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0
C C C C C C C C C C R R R R R R R R R R X
9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X

STe => will not wrap around
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0
C R C R C R C R C R C R C R C R C R C R X
9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X

Address 0x408
-------------
ST => will correctly wrap around at R9 when 512 kByte are installed
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0
C C C C C C C C C C R R R R R R R R R R X
9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X

STE => will not wrap around
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0
C R C R C R C R C R C R C R C R C R C R X
9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X

Address 0x40008
---------------
ST => will not wrap around
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
C C C C C C C C C C R R R R R R R R R R X
9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X

STe => will correctly wrap around at C8 when 128 kByte are installed
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
C R C R C R C R C R C R C R C R C R C R X
9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X

Address 0x80008
---------------
ST => will falsely wrap around at C8 when 128 kByte are installed
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
C C C C C C C C C C R R R R R R R R R R X
9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X

STE => will correctly wrap around at R9 when 512 kByte are installed
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
C R C R C R C R C R C R C R C R C R C R X
9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X



Address decoding during normal operation
========================================
After memory detection is finished, the MMU is configured to the actual
RAM bank size present in the computer.  If there is less than 2 MB in a
bank, the address decoding needs to be adapted.

For example, only 19 bits (address lines A0-A18) are used to address
512 kByte of RAM.  Furthermore, in a 512 kByte bank only row and column
address lines 0-8 exist.

The STe simply doesn't decode the topmost address lines (R9 and C9) in
this case, so for example the address 0x40008 is still decoded as:

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
C R C R C R C R C R C R C R C R C R X
8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X

The ST however modifies its address decoding to account for the missing
lines R9 and C9 as follows:

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
C C C C C C C C C R R R R R R R R R X
8 7 6 5 4 3 2 1 0 8 7 6 5 4 3 2 1 0 X

Christian Zietz, May 2016
