summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM/MEMM/EMMINIT.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/MEMM/MEMM/EMMINIT.ASM')
-rw-r--r--v4.0/src/MEMM/MEMM/EMMINIT.ASM678
1 files changed, 678 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/MEMM/EMMINIT.ASM b/v4.0/src/MEMM/MEMM/EMMINIT.ASM
new file mode 100644
index 0000000..65527b9
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EMMINIT.ASM
@@ -0,0 +1,678 @@
1
2
3 page 58,132
4;******************************************************************************
5 title EMMINIT - Expanded Memory Manager initialization
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EMMINIT - Expanded Memory Manager initialization routine
13;
14; Version: 0.05
15;
16; Date: May 24 ,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change Log:
23;
24; DATE REVISION Description
25; -------- -------- --------------------------------------------
26; 04/16/86 Original Adapted from DOS clock driver.
27; 05/24/86 0.00 From EMML test driver.
28; 06/21/86 0.02 added cld to EMM_Init
29; 06/28/86 0.02 Name change from MEMM386 to MEMM
30; 06/29/86 0.02 INC AX (was INC AL) for emm_free init
31; 07/06/86 0.04 Size _emm_page,_emm_free, & _pft386 based
32; on # of pages in system
33; 07/06/86 0.04 Changed assume to DGROUP
34; 07/10/86 0.05 moved int 67h patch to INIT
35; 06/07/88 added FRS_array initialization (Paul Chan)
36;
37;******************************************************************************
38; Functional Description:
39; This module initializes the data structures for the EMM
40; and sets the current emm data break address (_emm_brk).
41;
42;******************************************************************************
43.lfcond
44.386p
45 page
46;******************************************************************************
47; P U B L I C D E C L A R A T I O N S
48;******************************************************************************
49;
50 public EMM_Init
51 page
52;******************************************************************************
53; L O C A L C O N S T A N T S
54;******************************************************************************
55;
56 include vdmseg.inc
57 include emmdef.inc
58
59FALSE equ 0
60TRUE equ not FALSE
61
62EMM_HW_ERROR equ 81h ; EMM h/w error status
63
64;******************************************************************************
65; E X T E R N A L R E F E R E N C E S
66;******************************************************************************
67;
68_DATA segment
69
70extrn pool_size:word ; size of EMM Pages Pool in kbytes
71extrn xbase_addr_h:byte ; bit 16-24 of address of first byte of emm memory
72extrn xbase_addr_l:word ; bit 0-15 of address of first byte of emm memory
73extrn sys_size:word ; number of 16k pages taken away from conv. mem
74extrn PageT_Seg:word ; segment of system page table
75
76extrn _PF_Base:word ; segment addr of page frame base
77extrn _page_frame_pages:word ; number of pages in 3.2 page frame
78
79extrn _EMMstatus:word ; status of EMM
80
81extrn _page_frame_base:word ; pointers into page tables for each window
82extrn _mappable_pages:word ; mappable page array
83extrn _EMM_MPindex:byte ; index into mappable page array
84extrn _physical_page_count:word ; number of physical pages
85extrn _mappable_page_count:word ; number of mappable pages
86
87extrn _cntxt_pages:word ; pages in a context
88extrn _cntxt_bytes:word ; bytes in a context
89
90extrn _emm_page:word ; ptr to array of EMM pages
91extrn _free_count:word ; # of free EMM pages
92extrn _emmpt_start:word ; start of empty part of emm page
93extrn _emm_free:word ; ptr to array of free EMM pages
94extrn _free_top:word ; top of _emm_free
95
96extrn _total_pages:word ; total # of EMM pages available
97extrn _pft386:word ; ptr to array of page table entries
98
99extrn _emm_brk:word ; offset for emm data break address
100
101extrn FRS_array:word ;
102extrn CurRegSetn:byte
103extrn CurRegSet:word
104extrn FRS_free:byte
105
106extrn _handle_table:word
107extrn _handle_count:word
108
109_DATA ends
110
111ifndef NOHIMEM
112else
113VDATA segment
114extrn vdata_begin:byte
115VDATA ends
116endif
117
118LAST segment
119extrn mappable_segs:byte
120LAST ends
121
122_TEXT segment
123extrn InitELIM:far
124_TEXT ends
125
126LAST segment
127extrn InitEPage:near
128LAST ends
129
130
131 page
132;******************************************************************************
133; S E G M E N T D E F I N I T I O N
134;******************************************************************************
135;
136;******************************************************************************
137;
138; Code Segment
139;
140;******************************************************************************
141;******************************************************************************
142; MACROS used in the EMM initialisation code
143;******************************************************************************
144;******************************************************************************
145;
146; Get_FRS_window - get pointer to Fast Register Set window
147;
148; ENTRY: Reg - points to an FRS_struc
149;
150; EXIT: Reg - points to FRS_window entry in the structure
151;
152; USES: Reg
153;
154;******************************************************************************
155Get_FRS_window MACRO Reg
156
157 mov Reg, word ptr [CurRegSet] ; just offset (assume dgroup)
158 add Reg, FRS_window ; points to FRS window entries
159 ENDM
160
161;******************************************************************************
162;**init_PAGE_FRAME_BASE: macro to fill in the page_frame_base array. this
163; array contains the selector:offset into page table. The selector is already
164; initialised. So the offset of each of the physical pages into the page
165; table needs to be filled in.
166;
167; ENTRY: SI = INDEX INTO _page_frame_base, also physical page #
168; BX = Segment of physical page
169;
170;******************************************************************************
171init_page_frame_base MACRO
172;
173 push si
174 push bx
175;
176 shl si,2 ; convert index into offset in dword array
177;
178 shr bx,6 ; convert segment into page table offset
179 ; since there is 1 dword entry for each 4k
180 ;
181 mov _page_frame_base[si],bx ; fill this in
182;
183 pop bx
184 pop si
185;
186 ENDM
187
188;******************************************************************************
189;**init_MAPPABLE_PAGES: macro to fill the _mappable_pages array. this array
190; contains the segment and physical page number of all the mappable physical
191; pages.
192;
193; ENTRY: SI = INDEX INTO _page_frame_base, also physical page #
194; BX = Segment of physical page
195; DI = Index into _mappable_pages
196;
197;******************************************************************************
198init_mappable_pages MACRO
199;
200 push di
201;
202 shl di,2 ; convert index into offset in dword array
203;
204 mov _mappable_pages[di],bx ; fill in segment
205 mov _mappable_pages[di][2],si ; and physical page number
206;
207 pop di
208;
209 ENDM
210
211;******************************************************************************
212;**init_MAPPABLE_INDEX: macro to fill in EMM_MPIndex array. This array
213; contains a cross reference for the memory from 4000h to 10000h into the
214; mappable_pages array. There is an entry for each 16k page. The pages in
215; this range which are not mappable are initialised to -1. The ones which
216; are mappable are initialised to the index into the mappable_pages array
217; for the entry which represents this page
218;
219; ENTRY: DI = Index into _mappable_pages
220; BX = Segment of physical page
221;
222;******************************************************************************
223init_mappable_index MACRO
224;
225 push ax
226 push bx
227;
228 shr bx,10 ; convert segment to 16k page #
229 sub bx,CONV_STRT_PG ; first page in EMM_MPIndex array is 16
230;
231 mov ax,di ; to extract the lower byte
232 mov _EMM_MPIndex[bx],al ; fill in index
233;
234 pop bx
235 pop ax
236;
237 ENDM
238
239;******************************************************************************
240; INVALIDATE_MAPPABLE_PAGE_ENTRY: macro to remove the page from the mappable
241; page temporary list we are using. this is to facilitate the recognition
242; of pages above A000 which are not page frame pages. When we recognise page
243; frame pages we invalidate them so that the subsequent pass for pages doesn't
244; include these.
245;
246; ENTRY: BX = Segment of physical page
247;******************************************************************************
248inv_mpbl MACRO
249;
250 push bx
251;
252 shr bx,10 ; convert segment to 16k page #
253 mov cs:mappable_segs[bx],PAGE_NOT_MAPPABLE
254;
255 pop bx
256;
257
258 ENDM
259
260;
261LAST segment USE16
262 assume cs:LAST, ds:DGROUP, es:DGROUP
263
264;******************************************************************************
265; LOCAL VARIABLES
266;******************************************************************************
267first_sys_ppage dw 0ffffh ; physical page number of first system page
268
269 page
270;******************************************************************************
271;
272; CODE FOR INITIALISATION
273;
274;******************************************************************************
275
276
277 page
278;******************************************************************************
279; EMM_Init - initialization routine for EMM.
280; Patches int 67h vector.
281;
282; ENTRY: none
283;
284; EXIT: EMM vector initialized.
285; EMM data structures initialized
286; NC => no errors
287; C => errors
288;
289; USED: none
290;
291;******************************************************************************
292EMM_Init proc near
293;
294 pusha
295 push ds
296 push es
297;
298; set DS,ES to DGROUP segment
299;
300 mov ax,seg DGROUP
301 mov ds,ax
302 mov es,ax
303;
304 cld ; strings foward
305;
306; init EMM status
307;
308 mov [_EMMstatus],0
309
310;
311; set total # of EMM pages
312;
313 mov cx,[pool_size] ; CX = kbytes of expanded memory
314 shr cx,4 ; CX = # of EMM pages available
315 mov [_total_pages],cx ; pages total
316;
317; init ptrs for _emm_page, _emm_free and _pft386
318;
319 shl cx,1 ; CX = bytes in total_pages words
320
321ifndef NOHIMEM
322else
323 mov ax,seg VDATA
324 sub ax,seg DGROUP
325 shl ax,4 ; convert into offset from dgroup
326 add ax,offset VDATA:vdata_begin
327 mov [_emm_page],ax
328endif
329
330
331 mov ax,[_emm_page] ; AX = ptr to emm_page array
332 add ax,cx ; AX = ptr to word just past emm_page[]
333 mov [_emm_free],ax ; set ptr for emm_free[]
334 add ax,cx ; AX = ptr to word just past emm_free[]
335 mov [_pft386],ax ; set ptr for _pft386[]
336 shl cx,1 ; CX = bytes in total_pages dwords
337 add ax,cx ; AX = ptr to word just past _pft386[]
338 mov [_emm_brk],ax ; set break address for emm data
339 shr cx,2 ; CX = total_pages again
340;
341; init free pages array
342;
343 mov [_free_count],cx ; all pages free initially
344 mov [_free_top],0 ; top ptr pts to first free page
345 mov di,[_emm_free] ; ES:DI pts to _emm_free[0]
346 mov bx,[_free_top] ; BX = current top of free list
347 shl bx,1
348 add di,bx ; ES:DI pts to begin of free page area
349 xor ax,ax ; start with EMM page#0
350EMMP_loop: ; copy free pages into _emm_free
351 stosw ; store EMM page#
352 inc ax ;(0.02) increment page#
353 loop EMMP_loop ;Q: all entries in _emm_free[] ?
354 ; N: do next page.
355;
356; fix _page_frame_pages to be a maximum of 4 (for the LIM 3.2 frame)
357;
358 cmp [_page_frame_pages],4
359 jbe EMIN_1
360 mov [_page_frame_pages],4
361EMIN_1:
362;
363; See validity of page frame
364;
365 test [_PF_base],3ffh ; if any of these bits are set it is
366 ; invalid
367 jne EMIN_2 ;
368 cmp [_PF_base],0E400h ; in the ROM area
369 jae EMIN_2 ; also invalid
370 cmp [_PF_base],0C000h ; or in the video area
371 jnb EMIN_3 ;
372EMIN_2:
373;
374; Page Frame invalid, set it to FFFFh and _page_frame_pages to 0
375;
376 mov [_PF_base],0FFFFh
377 mov [_page_frame_pages],0
378;
379EMIN_3:
380;
381; setting up _page_frame_base
382; _mappable_pages
383; _EMM_MPIndex
384; _physical_page_count
385; _mappable_page_count
386;
387;
388;
389; ----------------- ----------------- -----------------
390; | for pages | | for pages | | |FC00h
391; | below | | below | |---------------|
392; | A000h | | A000h | | |
393; ----------------- ----------------- | |
394; | | | | | . |
395; | for pages | | for pages | | . |
396; | above | | above | | . |
397; | A000h | | A000h | <-- | |
398; | | | | | |---------------|
399; ----------------- ----------------- | | |4800h
400; | for page frame| | for page frame| | |---------------|
401; | pages even if | | pages only if | |------- |4400h
402; | they don't | | they exist | |---------------|
403; | exist | | | | |4000h
404; ----------------- ----------------- -----------------
405;
406; _page_frame_base _mappable_pages EMM_MPIndex
407;
408; Each entry reps Each entry reps Each entry reps
409; a physical page. a mappable ph. page a system page
410;
411; DWORD. DWORD Byte
412;
413; 1st WORD: offset 1st WORD: segment Index into
414; into page table of ph. page _mappable_pages
415; which reps the page
416; 2nd WORD: sel. 2nd WORD: physical
417; of page table page # of ph. page
418;
419;
420; 1. Set up for the page frame pages. Note that they may or may not exist.
421; Even if they do not exist entries must be set up for them in the
422; _page_frame_base.
423;
424 ;
425 ; initialise indexes.
426 ;
427 xor si,si ; index into _page_frame_pages
428 ; thus also physical page number
429 xor di,di ; index into _mappable_pages
430 ;
431 ; set up for page frame pages
432 ;
433 mov cx,[_page_frame_pages] ; get number
434 jcxz EMIN_5 ; if none exist then skip next portion
435 ;
436 mov bx,[_PF_base] ; get page frame base
437 ;
438 ; the setup loop:
439 ;
440EMIN_4:
441 init_page_frame_base
442 init_mappable_pages
443 init_mappable_index
444 inv_mpbl
445 ;
446 ; update counters for next entry
447 ;
448 inc si
449 inc di
450 add bx,0400h
451 ;
452 ; and loop back
453 ;
454 loop EMIN_4
455;
456EMIN_5:
457;
458; 2. If page frame pages were less than 4 then also we should set aside
459; four entries in the physical page array
460;
461 mov si,4
462;
463; 3. Setup for the mappable pages above A000h. Search the mappable_segs
464; array for mappable pages above A000h and for each mappable page make
465; an entry in the arrays
466;
467 ;
468 ; setup the segment and the count of pages we have to look for. also
469 ; the index into the mappable_segs array
470 ;
471 mov bx,0A000h ; segment
472 mov dx,bx ;
473 shr dx,10 ; page # corresponding to segment
474 ;
475 mov cx,64 ; max page #
476 sub cx,dx ;
477 ;
478 ; setup loop
479EMIN_6:
480 ;
481 ; see if page mappable
482 ;
483 xchg dx,bx
484 cmp cs:mappable_segs[bx],PAGE_MAPPABLE ;
485 xchg dx,bx
486 jnz EMIN_7
487 ;
488 ; page mappable. set up entries for it
489 ;
490 init_page_frame_base ; set up the page_frame_base entry
491 init_mappable_pages ; set up the mappable_pages entry
492 init_mappable_index ; set up the EMM_MPIndex
493 ;
494 ; update counters for next entry
495 ;
496 inc si ; these two are only updated
497 inc di ; if an entry is found
498EMIN_7:
499 inc dx ; and these two are updated in
500 add bx,0400h ; any case
501 ;
502 ; and loop back
503 ;
504 loop EMIN_6
505
506;
507; 4. Finally set up for the system pages
508;
509 ;
510 ; store the physical page # of the 1st system page.
511 ;
512 mov cs:[first_sys_ppage],si
513 ;
514 ; setup the segment and the count of pages we have to look for. also
515 ; the index into the mappable_segs array
516 ;
517 mov bx,04000h ; segment
518 mov dx,bx ;
519 shr dx,10 ; page # corresponding to segment
520 ;
521 mov cx,40 ; max page #
522 sub cx,dx ;
523 ; number of pages to be examined
524 ;
525 ; setup loop
526EMIN_8:
527 ;
528 ; see if page mappable.
529 ;
530 xchg dx,bx
531 cmp cs:mappable_segs[bx],PAGE_MAPPABLE ;
532 xchg dx,bx
533 jnz EMIN_9
534 ;
535 ; page mappable. set up entries for it
536 ;
537 init_page_frame_base ; set up the page_frame_base entry
538 init_mappable_pages ; set up the mappable_pages entry
539 init_mappable_index ; set up the EMM_MPIndex
540 ;
541 ; update counters for next entry
542 ;
543 inc si ; these two are only updated
544 inc di ; if an entry is found
545EMIN_9:
546 inc dx ; and these two are updated in
547 add bx,0400h ; any case
548 ;
549 ; and loop back
550 ;
551 loop EMIN_8
552;
553; 5. finally use the indexes to fill up the counts of the number of entries in
554; each array.
555;
556 mov [_physical_page_count],si
557 mov [_mappable_page_count],di
558;
559;
560; 6. and the pages in a context and the number of bytes needed to save a
561; context.
562;
563 inc si ; cntxt_pages = (physical_page_count
564 ; + 1) & NOT 1
565 and si, NOT 0001h ; to round up si to higher even #
566 mov [_cntxt_pages],si ; number of pages in a context
567;
568 shl si,1
569 add si,2 ; cntxt_bytes = cntxt_pages*2 + 2
570 mov [_cntxt_bytes],si ;
571;
572
573;
574; initialize FRS_array
575;
576 lea si,FRS_array ; DS:SI <-- FRS_array
577 mov [si.FRS_alloc], 1 ; mark FRS set 0 as allocated
578 mov [CurRegSetn], 0 ; use FRS set 0
579 mov [FRS_free], FRS_COUNT-1 ; one less FRS set
580 mov word ptr [CurRegSet], SI; save current FRS pointer
581
582;
583; NOW for some Handle 0 initialisation. We have to reclaim the pages we
584; released to the emm page pool from the conventional memory. This is
585; easy. These happen to be the first k pages in the emm page pool. We
586; need to fix the following data structures to reclaim these.
587;
588; k pages need to be transferred to emm_page array from emm_free array
589; and emmpt_start, _free_top, _free_count and _handle_table and _handle_count
590; updated
591 ;
592 ; find out the number of pages to be reclaimed
593 ;
594 mov cx,[sys_size] ; in kb
595 shr cx, 4 ; convert to number of 16k pages
596 ;
597 ; transfer these many pages from the emm_free array to the emm_pages array
598 ;
599 push cx
600 ;
601 mov si,_emm_free ;
602 add si,_free_top ;
603 add si,_free_top ; get offset to free page
604 ;
605 mov di,_emm_page ;
606 add di,_emmpt_start ;
607 add di,_emmpt_start ; get offset to next available loc in
608 ; emm_page
609 ;
610 cld
611 rep movsw ; transfer the pages over
612 ;
613 pop cx
614 ;
615 ; fix entry for handle 0 in handle table
616 ;
617 mov dx, [_emmpt_start]
618 mov _handle_table[0],dx ; offset into emm_page array
619 mov _handle_table[2],cx ; number of pages
620 ;
621 ; handle_count needs to be incremented to indicate that handle 0 is
622 ; allocated
623 ;
624 inc [_handle_count]
625 ;
626 ; fix ptr in emm page tracking arrays
627 ;
628 add [_emmpt_start],cx
629 add [_free_top],cx
630 sub [_free_count],cx
631;
632; Initialise FRS initialisation
633;
634; di = pointer into FRS. bx = physical page number. si = pointer into emm_page
635; cx = number of pages mapped.
636;
637 mov si,_handle_table[0] ; get pointer into emm_page
638 shl si,1 ; emm_page is a word array
639 add si,[_emm_page] ;
640 ;
641 GET_FRS_WINDOW di ; get pointer to FRS area
642
643 mov bx,cs:[first_sys_ppage]
644 shl bx,1
645 add di,bx ;
646 ;
647 cld
648 rep movsw
649 ;
650;
651; the way we have allocated the pages we don't need to update the Page table
652; the pages that have been mapped
653;
654; init ELIM h/w emulation (DMA PORTS)
655;
656 call InitELIM
657
658;
659; init EMM_PTE - ptrs to EMM pages
660;
661 call InitEPage
662;
663; leave - no errors
664;
665 pop es
666 pop ds
667 popa
668;
669 xor ax,ax
670 clc
671 ret
672;
673EMM_Init endp
674
675;
676LAST ends
677
678 end