1 BREAK <EMM control sector layout>
4 ; The EMM control sector is a 1024 byte record which ALWAYS occupies the
5 ; very first 1024 bytes of "extra" memory that needs to be managed. Its
6 ; function is to provide a method to allocate available "extra" memory
7 ; to programs which desire to use it and avoid program conflicts that
8 ; would occur if two different programs attempted to use the same piece
13 ; The EMM_CTRL structure defines the offsets into the 1024 byte control
14 ; sector of the various fields. The EMM_REC structure defines a sub-structure
15 ; contained within the EMM_CTRL structure which represents a particular
16 ; piece of allocated "extra" memory (an allocation record).
19 ; Layout of each EMM record.
24 EMM_BASE DD ? ; 24 bit address of start of region
25 EMM_KSIZE DW ? ; Size of region in kbytes
29 EMM_ALLOC EQU 0000000000000001B ; Zero -> record is free
30 EMM_ISDRIVER EQU 0000000000000010B ; 1 -> driver is installed
34 EMM_EMM EQU 0 ; Allocated to EMM
39 ; Layout of EMM control 1024 byte record
43 EMM_TOTALK DW ? ; EXCLUDING the 1k of this record
44 EMM_AVAILK DW ? ; Amount of above NOT allocated
45 DB SIZE EMM_REC DUP(?) ; NULL (0th) RECORD
46 EMM_RECORD DB (1024 - 50 - 4 - 10 - (SIZE EMM_REC)) DUP(?)
48 EMM_TAIL_SIG DB 10 DUP(?)
51 EMM_NUMREC EQU (1024 - 50 - 4 - 10 - (SIZE EMM_REC)) / (SIZE EMM_REC)
55 ; The current initial (no "extra" memory allocated) EMM_CTRL sector is
57 ; EMM_CONTROL LABEL BYTE
58 ; DB "MICROSOFT EMM CTRL VERSION 1.00 CONTROL BLOCK "
59 ; DW EXTMEM_TOTALK - 1
60 ; DW EXTMEM_TOTALK - 1
62 ; DW EMM_ALLOC + EMM_ISDRIVER
64 ; DW EXTMEM_LOW + 1024
71 ; Where EXTMEM_LOW:EXTMEM_HIGH is the 32 bit address of the first byte
72 ; of the EMM_CTRL sector (first byte of "extra" memory) and EXTMEM_TOTALK
73 ; is the size in K of the available "extra" memory. One is subtracted
74 ; from EXTMEM_TOTALK because the sizes in the EMM_CTRL record DO NOT
75 ; include the 1k taken up by the EMM_CTRL sector.
77 ; The reason for the existance of the NULL 0th record is to facilitate
78 ; the computation of EMM_BASE for the first EMM_REC allocation record
81 ; The EMM_REC structures CANNOT be sparse. In other words if one sets
82 ; up a scan of the EMM_REC structures in the EMM_CTRL sector, as soon as
83 ; an EMM_REC structure WITHOUT the EMM_ALLOC bit set in its flag word
84 ; is encountered it is not necessary to scan further because it IS KNOWN
85 ; that all of the EMM_REC structures after the first one with EMM_ALLOC
86 ; clear also have EMM_ALLOC clear. What this means is that EMM_CTRL
87 ; memory CANNOT BE deallocated. Once an EMM_REC structure has its
88 ; EMM_ALLOC bit set, there is NO correct program operation which
89 ; can clear the bit UNLESS it IS KNOWN that the next EMM_REC structure
90 ; has its EMM_ALLOC bit clear or the EMM_REC structure is the last one.
93 ; USING THE EMM_CTRL SECTOR:
95 ; A program which wishes to use the EMM_CTRL sector to access "extra"
96 ; memory should work as follows:
98 ; Figure out how much memory you wish to allocate
100 ; Figure out the location and size of the "extra" memory in the system
102 ; IF (the first 1024 bytes of "extra" memory DO NOT contain a valid
103 ; EMM_CTRL record determined by checking for the existence of the
104 ; correct EMM_VER and EMM_TAIL_SIG strings)
105 ; Write a correct initial EMM_CTRL sector to the first 1024
106 ; bytes of extra memory. Be sure to fill in EMM_TOTALK,
107 ; EMM_AVAILK and EMM_BASE in the 0th record.
109 ; Set up a scan of the EMM_REC structures in the EMM_CTRL sector.
110 ; NOTE: You can skip the NULL 0th record if you want since it has
113 ; FOR (i=0;i<EMM_NUMREC;i++)
114 ; IF ( this EMM_REC has EMM_ALLOC clear)
115 ; IF ( EMM_AVAILK < amount I want to alloc)
116 ; ERROR insufficient memory
117 ; EMM_AVAILK = EMM_AVAILK - amount I want to alloc
118 ; EMM_FLAGS = EMM_ALLOC + EMM_ISDRIVER
119 ; EMM_KSIZE = amount I want to alloc
120 ; EMM_SYSTEM = appropriate value
121 ; EMM_BASE = EMM_BASE of PREVIOUS EMM_REC +
122 ; (1024 * EMM_KSIZE of PREVIOUS EMM_REC)
125 ; address next EMM_REC structure
127 ; IF (i >= EMM_NUMREC)
128 ; ERROR no free EMM_REC structures
131 ; You can now see why we need that NUL 0th EMM_REC structure. In order to
134 ; EMM_BASE = EMM_BASE of PREVIOUS EMM_REC +
135 ; (1024 * EMM_KSIZE of PREVIOUS EMM_REC)
137 ; when the very first EMM_REC is allocated we must have a "previous EMM_REC"
138 ; structure to point at.
140 ; The above code is rather simplistic in that all it does is do a simple
141 ; allocation. The EMM_ISDRIVER bit allows us to do some more sophisticated
142 ; things. In particular in the case of a RAMDrive type of program it is
143 ; desirable to "re-find" the same RAMDrive area in "extra" memory when the
144 ; system is re-booted. The EMM_ISDRIVER bit is used to help us do this.
146 ; The EMM_ISDRIVER bit means "there is presently a piece of code in the
147 ; system which is using this memory". If we find an EMM_REC structure
148 ; which has its EMM_ALLOC bit set, but the EMM_ISDRIVER bit is clear
149 ; it means that the piece of code that originally allocated
150 ; the memory is gone and we may want to "re-find" this memory by
151 ; setting the EMM_ISDRIVER bit again. A RAMDrive program would have
152 ; slightly different code than the above:
154 ; FOR (i=0;i<EMM_NUMREC;i++)
155 ; IF ( this EMM_REC has EMM_ALLOC clear)
156 ; IF ( EMM_AVAILK < amount I want to alloc)
157 ; ERROR insufficient memory
158 ; EMM_AVAILK = EMM_AVAILK - amount I want to alloc
159 ; EMM_FLAGS = EMM_ALLOC + EMM_ISDRIVER
160 ; EMM_KSIZE = amount I want to alloc
161 ; EMM_SYSTEM = appropriate value
162 ; EMM_BASE = EMM_BASE of PREVIOUS EMM_REC +
163 ; (1024 * EMM_KSIZE of PREVIOUS EMM_REC)
166 ; IF ((EMM_SYSTEM == my value for EMM_SYSTEM) &&
167 ; (EMM_ISDRIVER is clear))
168 ; deal with differences between amount
169 ; I want to allocate and EMM_KSIZE
171 ; EMM_BASE is the base address of this piece
172 ; of memory and EMM_KSIZE is its size.
174 ; address next EMM_REC structure
176 ; In this way we "re-find" memory that was previosly allocated (presumably
177 ; by us, or a related program).
179 ; NOTE THAT THIS USE OF EMM_ISDRIVER REQUIRES SOME MECHANISM FOR CLEARING
180 ; EMM_ISDRIVER WHEN THE CODE OF INTEREST IS REMOVED FROM THE SYSTEM.
181 ; In the case of a RAMDrive program the code is removed whenever the system
182 ; is re-booted. For this reason a RAMDrive program will need code that is
183 ; invoked whenever a system re-boot is detected. What this code does is
184 ; scan the EMM_REC structures in the EMM_CTRL sector turning off the
187 ; FOR (i=0;i<EMM_NUMREC;i++)
188 ; IF ( this EMM_REC has EMM_ALLOC clear)
190 ; ELSE IF (EMM_SYSTEM == my value for EMM_SYSTEM)
191 ; clear EMM_ISDRIVER bit
192 ; address next EMM_REC
194 ; Note that this code clears ALL of the ISDRIVER bits for EMM_SYSTEM
195 ; values of a certain value. This means there is a GLOBAL piece of
196 ; re-boot code for ALL of the programs using a particular EMM_SYSTEM
197 ; value. An alternative is to have each EMM_CTRL user clear the
198 ; EMM_ISDRIVER bits ONLY for those EMM_REC structures that it allocated.
199 ; This requires that the program keep a record of which EMM_REC structures
200 ; it is responsible for:
202 ; FOR each of my EMM_REC structures
203 ; INDEX this EMM_REC structure in the EMM_CTRL sector
206 ; NOTE about this step:
208 ; deal with differences between amount
209 ; I want to allocate and EMM_KSIZE
211 ; in the above code. There are a lot of options here depending on the desired
212 ; behavior. If the NEXT EMM_REC structure has EMM_ALLOC clear, then it may
213 ; be possible for me to grow or shrink the block I found by adjusting
214 ; EMM_KSIZE and EMM_AVAILK. If the NEXT EMM_REC structure has EMM_ALLOC
215 ; set, then I am forced to either adjust the amount I want to allocate
216 ; to match EMM_KSIZE, or skip this EMM_REC without setting EMM_ISDRIVER.
218 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
219 ; for rom 1nt15 extended memory interface
223 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;