diff options
Diffstat (limited to 'v4.0/src/MEMM/EMM/EMM40.C')
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMM40.C | 571 |
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 | */ | ||
| 42 | extern struct handle_ptr handle_table[]; | ||
| 43 | extern Handle_Name Handle_Name_Table[]; /* Handle names */ | ||
| 44 | extern unsigned short handle_table_size; /* number of entries */ | ||
| 45 | extern 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 | */ | ||
| 55 | extern unsigned short *emm_page; /* _emm_page array */ | ||
| 56 | extern int free_count; /* current free count */ | ||
| 57 | extern int total_pages; /* number being managed */ | ||
| 58 | extern 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 | */ | ||
| 78 | extern unsigned short EMMstatus; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * 4.0 EXTRAS | ||
| 82 | */ | ||
| 83 | |||
| 84 | extern unsigned short emm40_info[5]; /* hardware information */ | ||
| 85 | extern struct mappable_page mappable_pages[]; /* mappable segments | ||
| 86 | and corresponding pages */ | ||
| 87 | extern short mappable_page_count; /* number of entries in above */ | ||
| 88 | extern short page_frame_pages; /* pages in the page frame */ | ||
| 89 | extern 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 */ | ||
| 94 | extern char cntxt_pages; /* pages in context */ | ||
| 95 | extern char cntxt_bytes; /* bytes in context */ | ||
| 96 | extern unsigned short PF_Base; | ||
| 97 | extern unsigned short VM1_EMM_Pages; | ||
| 98 | /*extern unsigned short VM1_EMM_Offset;*/ | ||
| 99 | extern long page_frame_base[]; | ||
| 100 | extern char EMM_MPindex[]; | ||
| 101 | extern long OSEnabled; /* OS/E function flag */ | ||
| 102 | extern long OSKey; /* Key for OS/E function */ | ||
| 103 | |||
| 104 | /****************************************************************************** | ||
| 105 | EXTERNAL FUNCTIONS | ||
| 106 | ******************************************************************************/ | ||
| 107 | extern struct handle_ptr *valid_handle(); /* validate handle */ | ||
| 108 | extern unsigned far *source_addr(); /* get DS:SI far ptr */ | ||
| 109 | extern unsigned far *dest_addr(); /* get ES:DI far ptr */ | ||
| 110 | extern unsigned wcopyb(); | ||
| 111 | extern unsigned copyout(); | ||
| 112 | extern 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 | */ | ||
| 131 | ReallocatePages() | ||
| 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 | */ | ||
| 210 | UndefinedFunction() | ||
| 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 | */ | ||
| 233 | GetMappablePAddrArray() | ||
| 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 | */ | ||
| 278 | GetInformation() | ||
| 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 | */ | ||
| 319 | GetSetHandleAttribute() | ||
| 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 | */ | ||
| 363 | GetSetHandleName() | ||
| 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 | */ | ||
| 436 | GetHandleDirectory() | ||
| 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 | */ | ||
| 514 | PrepareForWarmBoot() | ||
| 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 | */ | ||
| 536 | OSDisable() | ||
| 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 | ||