
|
Mapper Support Routines ASCII, 01-09-94
5. MAPPER SUPPORT ROUTINES
============================
MSX-DOS 2 contains routines to provide support for the memory mapper.
This allows MSX application programs or MSX-DOS transient programs to utilize
more than the basic 64k of memory, without conflicting with the RAM disk or
any other system software.
5.1 MAPPER INITIALIZATION
When the DOS kernel is initialized it checks that there is the memory
mapper in the system, and that there is at least 128k of RAM available. If
the kernel has found at least one slot which contains 128k of the mapper RAM,
it selects the slot which contains the largest amount of RAM (or the slot
with the smallest slot number, if there are two or more mapper slots which
have the same amount of RAM) and makes that slot usable as the system RAM.
When there is not enough memory on the memory mapper, MSX-DOS 2 won't start.
Next the kernel builds up a table of all the 16k RAM segments available
to this slot (primary mapper slot). The first four segments (64k) for the
user and the two highest numbered segments are allocated to the system, one
for the DOS kernel code and one for the DOS kernel workspace. All other
segments (at least two) are marked as free initially. Then the kernel builds
up the similar tables for other RAM slots, if any. All of these segments are
marked as free initially.
5.2 MAPPER VARIABLES AND ROUTINES
The mapper support routines use some variables in the DOS system area.
These tables may be referred and used by the user programs for the various
purposes, but must not be altered. The contents of the tables are as follows:
address function
+0 Slot address of the mapper slot.
+1 Total number of 16k RAM segments. 1...255 (8...255 for the
primary)
+2 Number of free 16k RAM segments.
+3 Number of 16k RAM segments allocated to the system (at least
6 for the primay)
+4 Number of 16k RAM segments allocated to the user.
+5...+7 Unused. Always zero.
+8... Entries for other mapper slots. If there is none, +8 will be
zero.
A program uses the mapper support code by calling various subroutines.
These are accessed through a jump table which is located in the MSX-DOS
system area. The contents of the jump table are as follows:
address entry name function
+0H ALL_SEG Allocate a 16k segment.
+3H FRE_SEG Free a 16k segment.
+6H RD_SEG Read byte from address A:HL to A.
+9H WR_SEG Write byte from E to address A:HL.
+CH CAL_SEG Inter-segment call. Address in IYh:IX
+FH CALLS Inter-segment call. Address in line after the call
instruction.
+12H PUT_PH Put segment into page (HL).
+15H GET_PH Get current segment for page (HL)
+18H PUT_P0 Put segment into page 0.
+1BH GET_P0 Get current segment for page 0.
+1EH PUT_P1 Put segment into page 1.
+21H GET_P1 Get current segment for page 1.
+24H PUT_P2 Put segment into page 2.
+27H GET_P2 Get current segment for page 2.
+2AH PUT_P3 Not supported since page-3 must never be changed. Acts
like a "NOP" if called.
+2DH GET_P3 Get current segment for page 3.
A program can use the extended BIOS calls for the mapper support to
obtain these addresses. The calls are provided because these addresses may be
changed in the future version, or to use mapper routines other than MSX-DOS
mapper support routines.
To use the extended BIOS, the program should test "HOKVLD" flag at FB20h
in page-3. If bit-0 (LSB) is 0, there is no extended BIOS nor the mapper
support. Otherwise, "EXTBIO" entry (see below) has been set up and it can be
called with various parameters. Note that this test is unnecessary for the
applications which are based on MSX-DOS (such as the program which is loaded
from the disk), and the program may proceed to the next step.
Next, the program sets the device number of the extended BIOS in
register D, the function number in register E, and required parameters in
other registers, and then calls "EXTBIO" at FFCAh in page-3. In this case,
the stack pointer must be in page-3. If there is the extended BIOS for the
specified device number, the contents of the registers AF, BC and HL are
modified according to the function; otherwise, they are preserved. Register
DE is always preserved. Note that in any cases the contents of the
alternative registers (AF', BC', DE' and HL') and the index registers (IX and
IY) are corrupted.
The functions available in the mapper support extended BIOS are:
* Get mapper variable table
Parameter: A = 0
D = 4 (device number of mapper support)
E = 1
Result: A = slot address of primary mapper
DE = reserved
HL = start address of mapper variable table
* Get mapper support routine address
Parameter: A = 0
D = 4
E = 2
Result: A = total number of memory mapper segments
B = slot number of primary mapper
C = number of free segments of primary mapper
DE = reserved
HL = start address of jump table
In these mapper support extended BIOS, register A is not required to be
zero. Note that, however, if there is no mapper support routine, the contents
of registers will not be modified, and the value which is not zero will be
returned in A otherwise. Thus, the existence of the mapper support routine
can be determined by setting zero in A at the calling and examining the
returned value of A.
The slot address of the primary mapper returned by the extended BIOS is
the same as the current RAM slot address in page-3, and, in the ordinary
environment (DISK-BASIC and MSX-DOS), the same RAM slot is also selected in
page-2. In MSX-DOS, this is also true in page-0 and page-1.
5.3 USING MAPPER ROUTINES
A program can request a 16k RAM segment at any time by calling the
"ALL_SEG" routine. This either returns an error if there are no free
segments, or the segment number of a new segment which the program can use. A
program must not use any segment which it has not explicitly allocated,
except for the four segments which make up the basic 64k of RAM.
A segment can be allocated either as a user segment or as a system
segment. User segments will be automatically freed when the program
terminates, whereas system segments are never freed unless the program frees
them explicitly. Normally, programs should allocate user segments.
RAM segments can be accessed by the "RD_SEG" and "WR_SEG" routines which
read and write bytes to specified segments. The routines "CAL_SEG" and
"CALLS" allow inter-segment calls to be done in much the same way as
inter-slot calls in the current MSX system.
Routines are provided to explicitly page a segment in, or to find out
which segment is in a particular page. There are routines in which the page
(0...3) is specified by the top two bits of an address in HL ("PUT_PH" and
"GET_PH"). And there are also specific routines for accessing each page
("GET_Pn" and "PUT_Pn"). These routines are very fast so a program should not
suffer in performance by using them.
Note that page-3 should never be altered since this contains the mapper
support routines and all the other system variables. Also great care must be
taken if page-0 is altered since this contains the interrupt and the slot
switching entry points. Pages 1 and 2 can be altered in any way.
None of the mapper support routines will disturb the slot selection
mechanism at all. For example when "PUT_P1" is called, the specified RAM
segment will only appear at address 4000h...7FFFh if the mapper slot is
selected in page-1. The "RD_SEG" and "WR_SEG" routines will always access the
RAM segment regardless of the current slot selection in the specified page,
but the mapper RAM slot must be selected in page-2.
5.4 ALLOCATING and FREEING SEGMENTS
The following two routines can be called to allocate or free segments.
All registers apart from AF and BC are preserved. An error is indicated by
the carry flag being set on return. The slot selection and RAM paging may be
in any state when these routines are called and both will be preserved. The
stack must not be in page-0 or page-2 when either of these routines are
called.
A program must not use any segment (apart from the four which make up
the basic 64k) unless it has specifically allocated it, and must not continue
to use a segment after it has been freed.
A segment may be allocated either as a user or a system segment. The
only difference is that user segments will be automatically freed when the
program terminates whereas system segments will not be. In general a program
should allocate a user segment unless it needs the data in the segment to
outlast the program itself. User segments are always allocated from the
lowest numbered free segment and system segments from the highest numbered
one.
An error from "allocate segment" usually indicates that there are no
free segments, although it can also mean that an invalid parameter was passed
in register A and B. An error from "free segment" indicates that the
specified segment number does not exist or is already free.
ALL_SEG - Parameters: A=0 => allocate user segment
A=1 => allocate system segment
B=0 => allocate primary mapper
B!=0 => allocate
FxxxSSPP slot address (primary mapper, if 0)
xxx=000 allocate specified slot only
xxx=001 allocate other slots than specified
xxx=010 try to allocate specified slot and, if it
failed, try another slot (if any)
xxx=011 try to allocate other slots than specified
and, if it failed, try specified slot
Results: Carry set => no free segments
Carry clear => segment allocated
A=new segment number
B=slot address of mapper slot (0 if
called as B=0)
FRE_SEG - Parameters: A=segment number to free
B=0 primary mapper
B!=0 mapper other than primary
Returns: Carry set => error
Carry clear => segment freed OK
5.5 INTER-SEGMENT READ AND WRITE
The following two routines can be called to read or write a single byte
from any mapper RAM segment. The calling sequence is very similar to the
inter-slot read and write routines provided by the MSX system ROM. All
registers apart from AF are preserved and no checking is done to ensure that
the segment number is valid.
The top two bits of the address are ignored and the data will be always
read or written via page-2, since the segment number specifies a 16k segment
which could appear in any of the four pages. The data will be read or written
from the correct segment regardless of the current paging or slot selection
in page-0 or page-1, but note that the mapper RAM slot must be selected in
page-2 when either of these routines are called. This is so that the routines
do not have to do any slot switching and so can be fast. Also the stack must
not be in page-2. These routines will return disabling interrupts.
RD_SEG - Parameters: A = segment number to read from
HL = address within this segment
Results: A = value of byte at that address
All other registers preserved
WR_SEG - Parameters: A = segment number to write to
HL = address within this segment
E = value to write
Returns: A = corrupted
All other registers preserved
5.6 INTER-SEGMENT CALLS
Two routines are provided for doing inter-segment calls. These are
modelled very closely on the two inter-slot call routines provided by the MSX
system ROM, and the specification of their usage is very similar.
No check is done that the called segment actually exists so it is the
user's responsibility to ensure this. The called segment will be paged into
the specified address page, but it is the user's responsibility to ensure
that the mapper slot is enabled in this page, since neither of these routines
will alter the slot selection at all. This is to ensure that they can be
fast.
The routine cannot be used to do an inter-segment call into page-3. If
this is attempted then the specified address in page-3 will simply be called
without any paging, since page-3 must never be altered. Calling into page-0
must be done with some care because of the interrupt and other entry point.
Also care must be taken that the stack is not paged out by these calls.
These routines, unlike inter-slot calls, do not disable interrupts
before passing control to the called routine. So they return to the caller in
the same state as before, unless the interrupt flag was modified by the
called routine.
Parameters cannot be passed in registers IX, IY, AF', BC', DE' or HL'
since these are used internally in the routine. These registers will be
corrupted by the inter-segment call and may also be corrupted by the called
routine. All other registers (AF, BC, DE and HL) will be passed intact to the
called routine and returned from it to the caller.
CAL_SEG - Parameters: IY = segment number to be called
IX = address to call
AF, BC, DE, HL passed to called routine
Other registers corrupted
Results: AF, BC, DE, HL, IX and IY returned from called routine.
All others corrupted.
CALLS - Parameters: AF, BC, DE, HL passed to called routine
Other registers corrupted
Calling sequence: CALL CALLS
DB SEGMENT
DW ADDRESS
Results: AF, BC, DE, HL, IX and IY returned from called routine.
All others corrupted.
5.7 DIRECT PAGING ROUTINES
The following routines are provided to allow programs to directly
manipulate the current paging state without having to access the hardware.
Using these routines ensures compatibility with any changes to the details of
the hardware. The routines are very fast and so using them will not
compromise the performance of programs.
Routines are provided to directly read or write to any of the four page
registers. No checking of the validity of the segment number is done so this
is the user's responsibility. Note that the value written in the register is
also written in memory and, if the register value is requested, the value
stored in memory will be returned and the one in the register will never be
read directly. This is done to avoid errors from hardware conflicts when
there are two or more mapper registers in the system. The user should always
manipulate the memory mapper through these routines.
The "GET" routines return values from internal images of the registers
without actually reading the registers themselves. This ensures that if a
segment is enabled by, for example, "PUT_P1" then a subsequent "GET_P1" call
will return the actual value. Reading the mapper register may produce a
different value because the top bits of the segment numbers are generally not
recorded.
Although a "PUT_P3" routine is provided, it is in fact a dummy routine
and will not alter the page-3 register. This is because the contents of the
page-3 register should never be altered. The "GET_P3" routine does behave as
expected to allow the user to determine what segment is in page-3.
Another pair of routines ("GET_PH" and "PUT_PH") is provided which are
identical in function except that the page is specified by the top two bits
of register H. This is useful when register HL contains an address, and these
routines do not corrupt register HL. "PUT_PH" will never alter the page-3
register.
PUT_Pn - Parameters: n = 0,1,2 or 3 to select page
A = segment number
Results: None
All registers preserved
GET_Pn - Parameters: n = 0,1,2 or 3 to select page
Results: A = segment number
All other registers preserved
PUT_PH - Parameters: H = high byte of address
A = segment number
Results: None
All registers preserved
GET_PH - Parameters: H = high byte of address
Results: A = segment number
All other registers preserved
Before using these direct paging routines to alter the paging state, a
program should first use the "GET_Pn" routines to determine the initial four
segments for when it needs to restore these. No program should assume fixed
values for these initial segments since they are likely to change in future
versions of the system.
|