summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM/EMM/EMM40.C
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/MEMM/EMM/EMM40.C
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/MEMM/EMM/EMM40.C')
-rw-r--r--v4.0/src/MEMM/EMM/EMM40.C571
1 files changed, 571 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/EMM/EMM40.C b/v4.0/src/MEMM/EMM/EMM40.C
new file mode 100644
index 0000000..cce3a64
--- /dev/null
+++ b/v4.0/src/MEMM/EMM/EMM40.C
@@ -0,0 +1,571 @@
1/*******************************************************************************
2 *
3 * (C) Copyright Microsoft Corp. 1986
4 *
5 * TITLE: VDMM
6 *
7 * MODULE: EMM40.C - EMM 4.0 functions code.
8 *
9 * VERSION: 0.00
10 *
11 * DATE: Feb 25, 1987
12 *
13 *******************************************************************************
14 * CHANGE LOG
15 * Date Version Description
16 * -------- -------- -------------------------------------------------------
17 * 02/25/87 0.00 Orignal
18 *
19 *******************************************************************************
20 * FUNCTIONAL DESCRIPTION
21 *
22 * Paged EMM Driver for the iAPX 386.
23 * Extra functions defined in the 4.0 spec required by Windows.
24 *
25 ******************************************************************************/
26
27/******************************************************************************
28 INCLUDE FILES
29 ******************************************************************************/
30#include "emm.h"
31/*#include "mem_mgr.h"*/
32
33
34/******************************************************************************
35 EXTERNAL DATA STRUCTURES
36 ******************************************************************************/
37/*
38 * handle_table
39 * This is an array of handle pointers.
40 * page_index of zero means free
41 */
42extern struct handle_ptr handle_table[];
43extern Handle_Name Handle_Name_Table[]; /* Handle names */
44extern unsigned short handle_table_size; /* number of entries */
45extern unsigned short handle_count; /* active handle count */
46
47/*
48 * EMM Page table
49 * this array contains lists of indexes into the 386
50 * Page Table. Each list is pointed to by a handle
51 * table entry and is sequential/contiguous. This is
52 * so that maphandlepage doesn't have to scan a list
53 * for the specified entry.
54 */
55extern unsigned short *emm_page; /* _emm_page array */
56extern int free_count; /* current free count */
57extern int total_pages; /* number being managed */
58extern unsigned emmpt_start; /* next free entry in table */
59
60/*
61 * EMM free table
62 * this array is a stack of available page table entries.
63 * each entry is an index into the pseudo page table
64 */
65/*extern unsigned free_stack_count; /* number of entries */
66
67/*
68 * Current status of `HW'. The way this is handled is that
69 * when returning status to caller, normal status is reported
70 * via EMMstatus being moved into AX. Persistant errors
71 * (such as internal datastructure inconsistancies, etc) are
72 * placed in `EMMstatus' as HW failures. All other errors are
73 * transient in nature (out of memory, handles, ...) and are
74 * thus reported by directly setting AX. The EMMstatus variable
75 * is provided for expansion and is not currently being
76 * set to any other value.
77 */
78extern unsigned short EMMstatus;
79
80/*
81 * 4.0 EXTRAS
82 */
83
84extern unsigned short emm40_info[5]; /* hardware information */
85extern struct mappable_page mappable_pages[]; /* mappable segments
86 and corresponding pages */
87extern short mappable_page_count; /* number of entries in above */
88extern short page_frame_pages; /* pages in the page frame */
89extern short physical_page_count; /* number of physical pages */
90/*extern char VM1_cntxt_pages; /* pages in a VM1 context */
91/*extern char VMn_cntxt_pages; /* pages in a VM context */
92/*extern char VM1_cntxt_bytes; /* bytes in a VM1 context */
93/*extern char VMn_cntxt_bytes; /* bytes in a VM context */
94extern char cntxt_pages; /* pages in context */
95extern char cntxt_bytes; /* bytes in context */
96extern unsigned short PF_Base;
97extern unsigned short VM1_EMM_Pages;
98/*extern unsigned short VM1_EMM_Offset;*/
99extern long page_frame_base[];
100extern char EMM_MPindex[];
101extern long OSEnabled; /* OS/E function flag */
102extern long OSKey; /* Key for OS/E function */
103
104/******************************************************************************
105 EXTERNAL FUNCTIONS
106 ******************************************************************************/
107extern struct handle_ptr *valid_handle(); /* validate handle */
108extern unsigned far *source_addr(); /* get DS:SI far ptr */
109extern unsigned far *dest_addr(); /* get ES:DI far ptr */
110extern unsigned wcopyb();
111extern unsigned copyout();
112extern unsigned short Avail_Pages();
113
114
115/******************************************************************************
116 ROUTINES
117 ******************************************************************************/
118
119/*
120 * Reallocate Pages
121 * parameters:
122 * bx -- new number of pages
123 * dx -- handle
124 * returns:
125 * bx -- new number of pages
126 *
127 * Change the number of pages allocated to a handle.
128 *
129 * ISP 5/23/88 Updated for MEMM
130 */
131ReallocatePages()
132{
133#define handle ((unsigned short)regp->hregs.x.rdx)
134
135 register struct handle_ptr *hp;
136 struct handle_ptr *hp_save;
137 unsigned new_size;
138 register unsigned n_pages;
139 register unsigned next;
140
141 if ( (hp = valid_handle(handle)) == NULL_HANDLE )
142 return; /* (error code already set) */
143
144 setAH((unsigned char)EMMstatus); /* Assume success */
145 new_size = regp->hregs.x.rbx;
146 if ( new_size == hp->page_count )
147 return; /* do nothing... */
148
149 if ( new_size > hp->page_count ) {
150 if ( new_size > total_pages ) {
151 setAH(NOT_ENOUGH_EXT_MEM);
152 return;
153 }
154 n_pages = new_size - hp->page_count;
155 if ( n_pages > Avail_Pages() ) {
156 setAH(NOT_ENOUGH_FREE_MEM);
157 return;
158 }
159 if ( hp->page_count == 0 )
160 next = hp->page_index = emmpt_start;
161 else
162 next = hp->page_index + hp->page_count;
163 hp->page_count = new_size;
164 if ( next != emmpt_start ) {
165 /*
166 * Must shuffle emm_page array to make room
167 * for the extra pages. wcopyb correctly
168 * handles this case where the destination
169 * overlaps the source.
170 */
171 wcopyb(emm_page+next, emm_page+next+n_pages,
172 emmpt_start - next);
173 /* Now tell other handles where their pages went */
174 hp_save = hp;
175 for ( hp = handle_table;
176 hp < &handle_table[handle_table_size]; hp++ )
177 if ( hp->page_index != NULL_PAGE &&
178 hp->page_index >= next )
179 hp->page_index += n_pages;
180 hp = hp_save;
181 }
182 emmpt_start += n_pages;
183 if ( get_pages(n_pages, next) == NULL_PAGE) { /* strange failure */
184 setAH(NOT_ENOUGH_FREE_MEM);
185 new_size = hp->page_count - n_pages; /* as it was! */
186 setBX(new_size);
187 goto shrink; /* and undo damage */
188 }
189 } else {
190 /* Shrinking - make handle point to unwanted pages */
191 shrink:
192 hp->page_count -= new_size;
193 hp->page_index += new_size;
194 free_pages(hp); /* free space in emm_page array */
195 /* Undo damage to handle, the index was not changed */
196 hp->page_count = new_size;
197 hp->page_index -= new_size;
198 }
199
200#undef handle
201}
202
203/*
204 * UndefinedFunction
205 *
206 * An undefined or unsupported function.
207 *
208 * 05/10/88 ISP No update needed
209 */
210UndefinedFunction()
211{
212 setAH(INVALID_FUNCTION);
213}
214
215/*
216 * Get Mappable Physical Address Array
217 * parameters:
218 * al == 0
219 * es:di -- destination
220 * returns:
221 * cx -- number of mappable pages
222 *
223 * parameters:
224 * al == 1
225 * returns:
226 * cx -- number of mappable pages
227 *
228 * Get the number of mappable pages and the segment address for each
229 * physical page.
230 *
231 * ISP 5/23/88 Updated for MEMM. u_ptr made into a far pointer.
232 */
233GetMappablePAddrArray()
234{
235 unsigned far *u_ptr;
236 int n_pages;
237 int i;
238 struct mappable_page *mp = mappable_pages;
239
240 n_pages = mappable_page_count;
241
242 if ( regp->hregs.h.ral == 0 ) {
243 if ( n_pages > 0 ) {
244 u_ptr = dest_addr(); /* ES:DI */
245 for (i=0 ; i < 48 ; i++)
246 if (EMM_MPindex[i] != -1)
247 copyout(((struct mappable_page far *)u_ptr)++,
248 mp + EMM_MPindex[i],
249 sizeof(struct mappable_page) );
250 }
251 } else if ( regp->hregs.h.ral != 1 ) {
252 setAH(INVALID_SUBFUNCTION);
253 return;
254 }
255 setCX(n_pages);
256 setAH((unsigned char)EMMstatus);
257}
258
259/*
260 * Get Expanded Memory Hardware Information
261 * parameters:
262 * al == 0
263 * es:di -- user array
264 * returns:
265 * es:di[0] = raw page size in paragraphs
266 * es:di[2] = number of EXTRA fast register sets
267 * es:di[4] = number of bytes needed to save a context
268 * es:di[6] = number of settable DMA channels
269 *
270 * parameters:
271 * al == 1
272 * returns:
273 * bx = number of free raw pages
274 * dx = total number of raw pages
275 *
276 * ISP 5/23/88 Updated for MEMM. Made u_ptr into far ptr.
277 */
278GetInformation()
279{
280 unsigned far *u_ptr;
281 unsigned pages;
282
283 if ( OSEnabled >= OS_DISABLED ) {
284 setAH(ACCESS_DENIED); /* Denied by operating system */
285 return;
286 }
287
288 if ( regp->hregs.h.ral == 0 ) {
289 u_ptr = dest_addr(); /* ES:DI */
290 emm40_info[2] = (short)cntxt_bytes; /* update size */
291 copyout(u_ptr, emm40_info, sizeof(emm40_info));
292 setAH((unsigned char)EMMstatus);
293 } else if ( regp->hregs.h.ral == 1 ) {
294 GetUnallocatedPageCount(); /* Use existing code */
295 } else
296 setAH(INVALID_SUBFUNCTION);
297}
298
299/*
300 * GetSetHandleAttribute
301 *
302 * parameters:
303 * al == 0
304 * returns:
305 * al == 0 -- volatile handles
306 *
307 * parameters:
308 * al == 1
309 * returns:
310 * ah = 91h -- Feature not supported
311 *
312 * parameters:
313 * al == 2
314 * returns:
315 * al == 0 -- Supports ONLY volatile handles
316 *
317 * 05/09/88 ISP No update needed
318 */
319GetSetHandleAttribute()
320{
321#define handle ((unsigned short)regp->hregs.x.rdx)
322
323 if ( regp->hregs.h.ral == 0 ) {
324 if (valid_handle(handle) == NULL_HANDLE)
325 return; /* (error code already set) */
326 setAX(EMMstatus << 8); /* AL = 0 [volatile attribute] */
327 } else if ( regp->hregs.h.ral == 1 ) {
328 setAH(FEATURE_NOT_SUPPORTED);
329 } else if ( regp->hregs.h.ral == 2 ) {
330 setAX(EMMstatus << 8); /* AL = 0 [volatile attribute] */
331 } else
332 setAH(INVALID_SUBFUNCTION);
333
334#undef handle
335}
336
337
338
339
340/*
341 * GetSetHandleName
342 *
343 * Subfunction 0 Gets the name of a given handle
344 * Subfunction 1 Sets a new name for handle
345 *
346 * parameters:
347 * al == 0
348 * es:di == Data area to copy handle name to
349 * dx -- handle
350 * returns:
351 * [es:di] == Name of DX handle
352 *
353 * parameters:
354 * al == 1
355 * ds:si == new handle name
356 * dx -- handle
357 * returns:
358 * ah = Status
359 *
360 * ISP 5/23/88 Updated for MEMM. Name made into far *. Copyin routine used
361 * to copy name in into handle name table.
362 */
363GetSetHandleName()
364{
365 register unsigned short handle = ((unsigned short)regp->hregs.x.rdx);
366 register char far *Name;
367
368 /* Validate subfunction */
369 if ( (regp->hregs.h.ral != 0) && (regp->hregs.h.ral != 1) ) {
370 setAH(INVALID_SUBFUNCTION);
371 return;
372 }
373
374 /* Validate handle */
375
376 if ( valid_handle(handle) == NULL_HANDLE )
377 return; /* (error code already set) */
378
379 /* Implement subfunctions 0 and 1 */
380 if ( regp->hregs.h.ral == 0 ) {
381 Name = (char far *)dest_addr(); /* ES:DI */
382 copyout(Name, Handle_Name_Table[handle & 0xFF], Handle_Name_Len);
383 setAH((unsigned char)EMMstatus);
384 } else if ( regp->hregs.h.ral == 1 ) {
385 GetHandleDirectory(); /* See if already there */
386 switch ( regp->hregs.h.rah ) {
387 case NAMED_HANDLE_NOT_FOUND:
388 break;
389 case DUPLICATE_HANDLE_NAMES:
390 return;
391 default:
392 if ( handle == regp->hregs.x.rdx )
393 break; /* same handle, OK */
394 regp->hregs.x.rdx = handle;
395 setAH(DUPLICATE_HANDLE_NAMES);
396 return;
397 }
398 Name = (char far *)source_addr();
399 copyin(Handle_Name_Table[handle & 0xFF], Name, Handle_Name_Len);
400 setAH((unsigned char)EMMstatus);
401 } else
402 setAH(INVALID_SUBFUNCTION);
403
404}
405
406
407
408
409/*
410 * GetHandleDirectory
411 *
412 * Subfunction 0 Returns a directory of handles and handle names
413 * Subfunction 1 Returns the handle specified by the name at [ds:si]
414 *
415 * parameters:
416 * al == 0
417 * es:di == Data area to copy handle name to
418 * returns:
419 * al == Number of entries in the handle_dir array
420 * [es:di] == Handle_Dir array
421 *
422 * parameters:
423 * al == 1
424 * [ds:si] == Handle name to locate
425 * returns:
426 * ah == Status
427 *
428 * parameters:
429 * al == 2
430 * returns:
431 * bx == Total handles in system
432 *
433 * ISP 5/23/88 Updated for MEMM. nameaddress and dir_entry made into far *
434 * copyin routine used to copy name into local area for search.
435 */
436GetHandleDirectory()
437{
438 char far *NameAddress;
439 register struct handle_ptr *hp;
440 struct Handle_Dir_Entry far *Dir_Entry;
441 unsigned short Handle_Num, Found;
442/*
443 * since all local variables are allocated on stack (SS seg)
444 * and DS and SS has grown apart (ie DS != SS),
445 * we need variables in DS seg (ie static variables) to pass
446 * to copyout(),copyin() and Names_Match() which expects those
447 * parameters that are near pointers to be in DS
448 *
449 * PC 08/03/88
450 */
451 static Handle_Name Name;
452 static unsigned short Real_Handle;
453
454 if ( regp->hregs.h.ral == 0 ) {
455 Dir_Entry = (struct Handle_Dir_Entry far *)dest_addr();
456 hp = handle_table;
457 for (Handle_Num = 0; Handle_Num < handle_table_size; Handle_Num++) {
458 if ( hp->page_index != NULL_PAGE) {
459 Real_Handle = Handle_Num;
460 copyout(Dir_Entry, &Real_Handle, sizeof(short));
461 copyout(Dir_Entry->Dir_Handle_Name, Handle_Name_Table[Handle_Num], Handle_Name_Len);
462 Dir_Entry++;
463 } hp++;
464 } setAX((EMMstatus << 8) + handle_count);
465 } else if ( regp->hregs.h.ral == 1 ) {
466 NameAddress = (char far *)source_addr();
467 copyin(Name, NameAddress, Handle_Name_Len);
468 hp = handle_table;
469 Found = 0;
470 Handle_Num = 0;
471 while ((Handle_Num < handle_table_size) && (Found < 2)) {
472 if ( hp->page_index != NULL_PAGE ) {
473 if (Names_Match(Name, Handle_Name_Table[Handle_Num])) {
474 Found++;
475 Real_Handle = Handle_Num;
476 }
477 } hp++;
478 Handle_Num++;
479 }
480 switch (Found) {
481 case 0:
482 setAH((unsigned char)NAMED_HANDLE_NOT_FOUND);
483 break;
484 case 1:
485 setDX(Real_Handle);
486 setAH((unsigned char)EMMstatus);
487 break;
488 default:
489 setAH((unsigned char)DUPLICATE_HANDLE_NAMES);
490 }
491
492 } else if ( regp->hregs.h.ral == 2 ) {
493 setBX(handle_table_size);
494 setAH((unsigned char)EMMstatus);
495 } else
496 setAH(INVALID_SUBFUNCTION);
497
498#undef handle
499}
500
501/*
502 * Prepare For Warm Boot
503 *
504 * Always ready to reboot the system so just return status = OK
505 *
506 * parameters:
507 * None
508 * returns:
509 * AH = EMMstatus
510 *
511 * 05/09/88 ISP No update needed.
512 *
513 */
514PrepareForWarmBoot()
515{
516 setAH((unsigned char)EMMstatus);
517}
518
519/*
520 * Enable/Disable OS/E Function Set Functions
521 *
522 * Enable/Disable access to functions 26, 28 and 30
523 *
524 * parameters:
525 * AL = 0 Enable Functions
526 * AL = 1 Disable Functions
527 * AL = 2 Return Access Key
528 * BX, CX Access Key
529 * returns:
530 * AH = EMMstatus
531 * BX, CX Access Key if successful
532 *
533 * 05/09/88 ISP Updated for MEMM. Removed check for pCurVMID
534 *
535 */
536OSDisable()
537{
538 unsigned char function = regp->hregs.h.ral;
539
540 if ( function > 2 ) {
541 setAH(INVALID_SUBFUNCTION);
542 return;
543 }
544
545 if ( OSEnabled == OS_IDLE ) { /* First invocation */
546 if ( function == 2 ) {
547 setAH(ACCESS_DENIED);
548 return;
549 }
550 OSKey = Get_Key_Val(); /* Suitably random number */
551 regp->hregs.x.rbx = (short)OSKey;
552 regp->hregs.x.rcx = (short)(OSKey >> 16);
553 } else { /* Check Key */
554 if ( (short)OSKey != regp->hregs.x.rbx
555 || (short)(OSKey >> 16) != regp->hregs.x.rcx ) {
556 setAH(ACCESS_DENIED);
557 return;
558 }
559 }
560 if ( function == 0 ) /* enable */
561 OSEnabled = 1;
562 else if ( function == 1 ) /* disable */
563 OSEnabled = 2;
564 else if ( function == 2 ) /* return key */
565 OSEnabled = 0;
566
567 setAH((unsigned char)EMMstatus);
568}
569
570
571 \ No newline at end of file