diff options
Diffstat (limited to 'v4.0/src/MEMM/EMM/EMMFUNCT.C')
| -rw-r--r-- | v4.0/src/MEMM/EMM/EMMFUNCT.C | 660 |
1 files changed, 660 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/EMM/EMMFUNCT.C b/v4.0/src/MEMM/EMM/EMMFUNCT.C new file mode 100644 index 0000000..7547536 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMFUNCT.C | |||
| @@ -0,0 +1,660 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * | ||
| 3 | * (C) Copyright Microsoft Corp. 1986 | ||
| 4 | * | ||
| 5 | * TITLE: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver | ||
| 6 | * EMMLIB.LIB - Expanded Memory Manager Library | ||
| 7 | * | ||
| 8 | * MODULE: EMMFUNCT.C - EMM functions code. | ||
| 9 | * | ||
| 10 | * VERSION: 0.10 | ||
| 11 | * | ||
| 12 | * DATE: June 14,1986 | ||
| 13 | * | ||
| 14 | ******************************************************************************* | ||
| 15 | * CHANGE LOG | ||
| 16 | * Date Version Description | ||
| 17 | * -------- -------- ------------------------------------------------------- | ||
| 18 | * 06/14/86 Changed status return to return only AH. And added | ||
| 19 | * PFlag to decide on selector versus segment on long | ||
| 20 | * address generation (SBP). | ||
| 21 | * 06/14/86 Moved save_current_map and restore_map to ASM (SBP). | ||
| 22 | * 06/15/86 Changed NULL_HANDLE to 0x0FFF (see emm.h) (SBP). | ||
| 23 | * 06/21/86 Moved MapHandlePage to ASM (SBP). | ||
| 24 | * Handle # passed to client has high byte = NOT (low byte) | ||
| 25 | * as in the Above Board (SBP). | ||
| 26 | * Valid_Handle -> ASM (SBP). | ||
| 27 | * 06/23/86 Make_Addr removed. source_addr and dest_addr added(SBP). | ||
| 28 | * 06/25/86 0.02 Dealloc checks for save area in use (SBP). | ||
| 29 | * 06/28/86 0.02 Name change from CEMM386 to CEMM (SBP). | ||
| 30 | * 06/29/86 0.02 Return after NOT_ENOUGH_FREE_MEM error in Allocate(SBP). | ||
| 31 | * 07/06/86 0.04 Changed _emm_page,_emm_free, & _pft386 to ptrs (SBP). | ||
| 32 | * 07/06/86 0.04 moved SavePageMap and RestorePageMap to .ASM (SBP). | ||
| 33 | * 07/08/86 0.04 moved GetSetPageMap to .ASM (SBP). | ||
| 34 | * 07/09/86 0.04 removed code which places handle # in _pft386 | ||
| 35 | * entry (SBP). | ||
| 36 | * 07/09/86 0.05 fixed bug in deallocate (SBP). | ||
| 37 | * 05/09/88 0.10 modified for MEMM, modifications are indicated in | ||
| 38 | * individual routines (ISP). | ||
| 39 | * | ||
| 40 | ******************************************************************************* | ||
| 41 | * FUNCTIONAL DESCRIPTION | ||
| 42 | * | ||
| 43 | * Paged EMM Driver for the iAPX 386. | ||
| 44 | * | ||
| 45 | * The basic concept is to use the 386's page tables to emulate | ||
| 46 | * the functions of an EMM board. There are several constraints | ||
| 47 | * that are a result of poor planning on the LIM specifiers part. | ||
| 48 | * - maximum of 64K instantaneously mapped. this will | ||
| 49 | * be faithfully emulated in this design | ||
| 50 | * - maximum of 8Mb of extended memory can be used. | ||
| 51 | * The actual reason for this is because each board | ||
| 52 | * can only support 128 16Kb pages and the limit of | ||
| 53 | * 4 Aboveboards implies 512 pages maximum. This will | ||
| 54 | * not be adhered to since the limit in unnecessary. | ||
| 55 | * | ||
| 56 | * The memory managed by this scheme can be discontiguous but | ||
| 57 | * a 16Kb EMM page can not be composed of discontiguous pieces. | ||
| 58 | * This is not necessary but does simplify the job of managing | ||
| 59 | * the memory. | ||
| 60 | * | ||
| 61 | * The LIM specification implies the existence of a partitioning | ||
| 62 | * of extended memory into `boards'. While this concept is not | ||
| 63 | * meaningfull in the 386 environment, a page to logical board | ||
| 64 | * mapping is provided to support some of the LIM specified | ||
| 65 | * functions: | ||
| 66 | * pages 0 to 127 map to board 0 | ||
| 67 | * pages 128 to 255 map to board 1 | ||
| 68 | * ... | ||
| 69 | * The pages in this case are logical pages and pages on the | ||
| 70 | * same logical board may actually reside on different physical | ||
| 71 | * boards. (In fact, if contiguous memory, a page could actually | ||
| 72 | * be split across 2 different boards.) | ||
| 73 | * | ||
| 74 | * A brief note on parameters: | ||
| 75 | * all parameters to EMM functions are passed in registers. | ||
| 76 | * on entry to the EMM dispatch code, the registers are pushed | ||
| 77 | * onto the stack. In order to access them, they are pointed | ||
| 78 | * to by a global variable (regp). Defines are used to name | ||
| 79 | * these parameters and make the code more readable. | ||
| 80 | * | ||
| 81 | * Definitions: | ||
| 82 | * Handle: | ||
| 83 | * 16 bit value that references a block of | ||
| 84 | * allocated memory. Internally, it is an index into a handle | ||
| 85 | * table. Externally, the high byte is the NOT of the low byte | ||
| 86 | * for compatibility with the Above Board EMM driver. | ||
| 87 | * | ||
| 88 | * EMM page: | ||
| 89 | * a 16Kb contiguous portion of memory, aligned on a | ||
| 90 | * 16Kb boundary in 8086 address space. In physical | ||
| 91 | * address space it can be aligned on a 4Kb boundary. | ||
| 92 | * | ||
| 93 | * page | ||
| 94 | * 386 page. 4Kb in size and 4Kb aligned in physical | ||
| 95 | * address space. | ||
| 96 | * | ||
| 97 | * far86 * | ||
| 98 | * An iAPX 86 style 32 bit pointer. It consists of | ||
| 99 | * a 16 bit offset in the low word and a base | ||
| 100 | * address in the high word. | ||
| 101 | * | ||
| 102 | * Logical page | ||
| 103 | * an EMM page allocated to a handle via allocatepages | ||
| 104 | * function. each such page has a logical page number. | ||
| 105 | * | ||
| 106 | * physical page frame | ||
| 107 | * the location in physical 8086 space that an EMM page | ||
| 108 | * gets mapped to. there are 4 such locations. they are | ||
| 109 | * contiguous starting at page_frame_base | ||
| 110 | * | ||
| 111 | * 386 page frame | ||
| 112 | * this is the physical page in 80386 physical | ||
| 113 | * address space. the address of a 386 page frame | ||
| 114 | * is the value placed in a 80386 page table entry's | ||
| 115 | * high 20 bits. | ||
| 116 | ******************************************************************************/ | ||
| 117 | |||
| 118 | /****************************************************************************** | ||
| 119 | INCLUDE FILES | ||
| 120 | ******************************************************************************/ | ||
| 121 | #include "emm.h" | ||
| 122 | |||
| 123 | |||
| 124 | /****************************************************************************** | ||
| 125 | EXTERNAL DATA STRUCTURES | ||
| 126 | ******************************************************************************/ | ||
| 127 | /* | ||
| 128 | * I/O Map | ||
| 129 | * map_size | ||
| 130 | * this is an array of port addresses, 4 ports per | ||
| 131 | * emulated board. Each emulated board has up to | ||
| 132 | * 128 16Kb EMM pages assigned. The size of the table, | ||
| 133 | * the number of ports used, is map_size | ||
| 134 | * map_size = (<number of 386 pages>/(128*4))*4 | ||
| 135 | */ | ||
| 136 | /*extern unsigned short iomap[]; */ | ||
| 137 | /*extern char map_size;*/ | ||
| 138 | |||
| 139 | /* | ||
| 140 | * map_known | ||
| 141 | * This flags is set whenever the user is given the I/O map | ||
| 142 | */ | ||
| 143 | /*extern char map_known; */ | ||
| 144 | |||
| 145 | /* | ||
| 146 | * page frame base | ||
| 147 | * this is a map of the linear addresses of the | ||
| 148 | * 4 16Kb EMM `physical' windows that the user | ||
| 149 | * accesses the EMM pages through. The entries | ||
| 150 | * of this array are far pointers into the page table. | ||
| 151 | * Thus, the address defined by page_frame_base[0] | ||
| 152 | * is the address of the long word that is the page | ||
| 153 | * table entry for the first EMM window. The reason for | ||
| 154 | * this obscurity is in speed of mapping -- it is used | ||
| 155 | * to directly obtain access to the entry to be programmed | ||
| 156 | */ | ||
| 157 | extern unsigned long page_frame_base[]; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * save_map | ||
| 161 | * This is an array of structures that save the | ||
| 162 | * current mapping state. Size is dynamically determined. | ||
| 163 | */ | ||
| 164 | extern struct save_map save_map[]; | ||
| 165 | |||
| 166 | /* | ||
| 167 | * handle_table | ||
| 168 | * This is an array of handle pointers. | ||
| 169 | * page_index of zero means free | ||
| 170 | */ | ||
| 171 | extern struct handle_ptr handle_table[]; | ||
| 172 | extern Handle_Name Handle_Name_Table[]; | ||
| 173 | extern unsigned short handle_table_size; /* number of entries */ | ||
| 174 | extern unsigned short handle_count; /* active handle count */ | ||
| 175 | |||
| 176 | /* | ||
| 177 | * EMM Page table | ||
| 178 | * this array contains lists of indexes into the 386 | ||
| 179 | * Page Frame Addresses (pft386). Each list is pointed to | ||
| 180 | * by a handle table entry and is sequential/contiguous. | ||
| 181 | * This is so that maphandlepage doesn't have to scan | ||
| 182 | * a list for the specified entry. | ||
| 183 | */ | ||
| 184 | extern unsigned short *emm_page; /* ptr to _emm_page array */ | ||
| 185 | extern unsigned short free_count; /* current free count */ | ||
| 186 | extern unsigned short total_pages; /* number being managed */ | ||
| 187 | extern unsigned short emmpt_start; /* next free entry in table */ | ||
| 188 | |||
| 189 | /* | ||
| 190 | * EMM free table | ||
| 191 | * this array is a stack of available page table entries. | ||
| 192 | * each entry is an index into pft386[]. | ||
| 193 | */ | ||
| 194 | extern unsigned short *emm_free; /* ptr to _emm_free array */ | ||
| 195 | extern unsigned short free_top; | ||
| 196 | |||
| 197 | /* | ||
| 198 | * Page frame table | ||
| 199 | * This array contains addresses of physical page frames | ||
| 200 | * for 386 pages. A page is refered to by an index into | ||
| 201 | * this array | ||
| 202 | */ | ||
| 203 | extern union pft386 *pft386; /* ptr to page frame table array */ | ||
| 204 | |||
| 205 | |||
| 206 | /* | ||
| 207 | * Current status of `HW'. The way this is handled is that | ||
| 208 | * when returning status to caller, normal status is reported | ||
| 209 | * via EMMstatus being moved into AX. Persistant errors | ||
| 210 | * (such as internal datastructure inconsistancies, etc) are | ||
| 211 | * placed in `EMMstatus' as HW failures. All other errors are | ||
| 212 | * transient in nature (out of memory, handles, ...) and are | ||
| 213 | * thus reported by directly setting AX. The EMMstatus variable | ||
| 214 | * is provided for expansion and is not currently being | ||
| 215 | * set to any other value. | ||
| 216 | */ | ||
| 217 | extern unsigned short EMMstatus; | ||
| 218 | |||
| 219 | /* | ||
| 220 | * debug & such | ||
| 221 | */ | ||
| 222 | /*unsigned null_count = 0; /* number of attempts to map null pages */ | ||
| 223 | |||
| 224 | |||
| 225 | /****************************************************************************** | ||
| 226 | EXTERNAL FUNCTIONS | ||
| 227 | ******************************************************************************/ | ||
| 228 | extern struct handle_ptr *valid_handle(); /* validate handle */ | ||
| 229 | extern unsigned far *source_addr(); /* get DS:SI far ptr */ | ||
| 230 | extern unsigned far *dest_addr(); /* get ES:DI far ptr */ | ||
| 231 | /*extern unsigned AutoUpdate(); /* update auto mode */ | ||
| 232 | extern unsigned wcopy(); | ||
| 233 | extern unsigned copyout(); | ||
| 234 | extern void reallocate(); | ||
| 235 | |||
| 236 | |||
| 237 | /****************************************************************************** | ||
| 238 | ROUTINES | ||
| 239 | ******************************************************************************/ | ||
| 240 | |||
| 241 | /* | ||
| 242 | * Avail_Pages() | ||
| 243 | * returns: number of available emm pages | ||
| 244 | * | ||
| 245 | * 06/09/88 PC added the function | ||
| 246 | */ | ||
| 247 | unsigned short | ||
| 248 | Avail_Pages() | ||
| 249 | { | ||
| 250 | return(free_count) ; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * get_pages(num,pto) | ||
| 255 | * num --- number of pages desired | ||
| 256 | * pto --- offset into emm_page array where the pages got are to be copied | ||
| 257 | * return value: | ||
| 258 | * emm_page[] index (pointer to list of allocated pages) | ||
| 259 | * NULL_PAGE means failure. | ||
| 260 | * | ||
| 261 | * 05/06/88 ISP Updated for MEMM removed handle as a parameter | ||
| 262 | */ | ||
| 263 | unsigned | ||
| 264 | get_pages(num,pto) | ||
| 265 | register unsigned num; | ||
| 266 | register unsigned pto; | ||
| 267 | { | ||
| 268 | register unsigned pg; | ||
| 269 | unsigned f_page; | ||
| 270 | |||
| 271 | if(free_count < num) | ||
| 272 | return(NULL_PAGE); /* not enough memory */ | ||
| 273 | free_count -= num; /* adjust free count */ | ||
| 274 | f_page = pg = pto; | ||
| 275 | /* emmpt_start += num; */ /* new offset of avail area */ | ||
| 276 | |||
| 277 | /* | ||
| 278 | * copy num elements from the emm_free array | ||
| 279 | * to the emm_page table array and update the | ||
| 280 | * corresponding page frame table entry (with a | ||
| 281 | * handle back pointer) | ||
| 282 | */ | ||
| 283 | wcopy(emm_free+free_top, emm_page+pg, num); | ||
| 284 | free_top += num; | ||
| 285 | return(f_page); | ||
| 286 | } | ||
| 287 | |||
| 288 | |||
| 289 | /* | ||
| 290 | * free_pages(hp) | ||
| 291 | * hp --- handle whose pages should be deallocated | ||
| 292 | * | ||
| 293 | * Free the pages associated with the handle, but don't free the handle | ||
| 294 | * | ||
| 295 | * 05/09/88 ISP Pulled out from the deallocate page routine | ||
| 296 | */ | ||
| 297 | void | ||
| 298 | free_pages(hp) | ||
| 299 | register struct handle_ptr *hp; | ||
| 300 | { | ||
| 301 | register unsigned next; | ||
| 302 | unsigned new_start; | ||
| 303 | unsigned h_size; | ||
| 304 | |||
| 305 | if (hp->page_count == 0) return ; | ||
| 306 | /* | ||
| 307 | * copy freed pages to top of free stack | ||
| 308 | */ | ||
| 309 | free_top -= hp->page_count; /* free_top points to new top */ | ||
| 310 | free_count += hp->page_count; /* bookkeeping */ | ||
| 311 | wcopy(emm_page+hp->page_index, /* addr of first of list */ | ||
| 312 | emm_free+free_top, /* addr of free space */ | ||
| 313 | hp->page_count); /* # of pages to be freed */ | ||
| 314 | |||
| 315 | /* | ||
| 316 | * now, the hard part. squeeze the newly created hole | ||
| 317 | * out of the emm_page array. this also requires updating the | ||
| 318 | * handle_table entry via the backlink in the pft386 array. | ||
| 319 | * | ||
| 320 | * do this in two phases: | ||
| 321 | * - copy the lower portion up to squeeze the hole out | ||
| 322 | * - readjust the handle table to point to the new | ||
| 323 | * location of the head element | ||
| 324 | */ | ||
| 325 | |||
| 326 | next = hp->page_index + hp->page_count; | ||
| 327 | if(next == emmpt_start ) /* any lists below? */ | ||
| 328 | { | ||
| 329 | /* no, all done */ | ||
| 330 | emmpt_start -= hp->page_count; | ||
| 331 | return; | ||
| 332 | } | ||
| 333 | |||
| 334 | new_start = emmpt_start - hp->page_count; | ||
| 335 | wcopy(emm_page+next, /* 1st of rest of list */ | ||
| 336 | emm_page+hp->page_index,/* addr of freed area */ | ||
| 337 | emmpt_start-next); /* size of block of pages */ | ||
| 338 | |||
| 339 | /* | ||
| 340 | * loop through the handle table entries, fixing up | ||
| 341 | * their page index fields | ||
| 342 | */ | ||
| 343 | h_size = hp->page_count; | ||
| 344 | hp->page_count = 0; /* not really necessary */ | ||
| 345 | for(hp=handle_table;hp < &handle_table[handle_table_size];hp++) | ||
| 346 | if((hp->page_index != NULL_PAGE) && | ||
| 347 | (hp->page_index >= next) ) | ||
| 348 | hp->page_index -= h_size; | ||
| 349 | emmpt_start = new_start; /* fix emmpt_start */ | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * get status | ||
| 354 | * no parameters | ||
| 355 | * | ||
| 356 | * return current status of EMM subsystem | ||
| 357 | * (which, due to superior design is always just fine) | ||
| 358 | * | ||
| 359 | * 05/06/88 ISP No Update needed for MEMM | ||
| 360 | */ | ||
| 361 | GetStatus() | ||
| 362 | { | ||
| 363 | setAH((unsigned char)EMMstatus); /* if we got here, we're OK */ | ||
| 364 | } | ||
| 365 | |||
| 366 | |||
| 367 | /* | ||
| 368 | * get page frame address | ||
| 369 | * no parameters | ||
| 370 | * | ||
| 371 | * return the address of where the pages get mapped | ||
| 372 | * in user space | ||
| 373 | * | ||
| 374 | * 05/06/88 ISP Updated this routine from WIN386 sources. | ||
| 375 | */ | ||
| 376 | GetPageFrameAddress() | ||
| 377 | { | ||
| 378 | extern unsigned short PF_Base; | ||
| 379 | extern unsigned short page_frame_pages; | ||
| 380 | |||
| 381 | /* | ||
| 382 | * return the 8086 style base address of | ||
| 383 | * the page frame base. | ||
| 384 | */ | ||
| 385 | if ( page_frame_pages < 4 ) { | ||
| 386 | setAH(EMM_HW_MALFUNCTION); /* GET LOST!!! */ | ||
| 387 | if ( PF_Base == 0xFFFF ) | ||
| 388 | setBX(0xB000); /* In case error is ignored */ | ||
| 389 | else | ||
| 390 | setBX(PF_Base); /* stunted page frame */ | ||
| 391 | return; | ||
| 392 | } | ||
| 393 | setBX(PF_Base); | ||
| 394 | setAH((unsigned char)EMMstatus); /* OK return */ | ||
| 395 | } | ||
| 396 | |||
| 397 | |||
| 398 | /* | ||
| 399 | * get unallocated page count | ||
| 400 | * no parameters | ||
| 401 | * | ||
| 402 | * returns: | ||
| 403 | * bx -- count of free pages | ||
| 404 | * dx -- total number of pages (free and allocated) | ||
| 405 | * | ||
| 406 | * 05/06/88 ISP No update needed for MEMM | ||
| 407 | */ | ||
| 408 | GetUnallocatedPageCount() | ||
| 409 | { | ||
| 410 | setBX(free_count); | ||
| 411 | setDX(total_pages); | ||
| 412 | setAH((unsigned char)EMMstatus); | ||
| 413 | } | ||
| 414 | |||
| 415 | /* | ||
| 416 | * allocate pages | ||
| 417 | * parameters: | ||
| 418 | * n_pages (bx) -- allocation size request | ||
| 419 | * | ||
| 420 | * allocates the requested number of pages, creates | ||
| 421 | * a handle table entry and returns a handle to the | ||
| 422 | * allocated pages. | ||
| 423 | * calls AllocateRawPages | ||
| 424 | * | ||
| 425 | * 05/09/88 ISP updated for MEMM. Only handle value returned, not handle | ||
| 426 | * value with high byte as not of handle value. call to get | ||
| 427 | * pages also updated to remove handle parameter. | ||
| 428 | */ | ||
| 429 | AllocatePages() | ||
| 430 | { | ||
| 431 | #define n_pages ((unsigned)regp->hregs.x.rbx) | ||
| 432 | if(handle_count == handle_table_size){ /* no more handles? */ | ||
| 433 | setAH(NO_MORE_HANDLES); /* nope */ | ||
| 434 | return; | ||
| 435 | } | ||
| 436 | |||
| 437 | if(n_pages == 0) { | ||
| 438 | setAH(ZERO_PAGES); | ||
| 439 | return; | ||
| 440 | } | ||
| 441 | |||
| 442 | AllocateRawPages() ; | ||
| 443 | } | ||
| 444 | #undef n_pages | ||
| 445 | |||
| 446 | /* | ||
| 447 | * allocate raw pages | ||
| 448 | * parameters: | ||
| 449 | * n_pages (bx) -- allocation size request | ||
| 450 | * | ||
| 451 | * allocates the requested number of raw pages, | ||
| 452 | * allocating 0 page is Okay | ||
| 453 | * calls allocated pages if non-zero. | ||
| 454 | * | ||
| 455 | * CREATED : 08/08/88 PLC | ||
| 456 | */ | ||
| 457 | AllocateRawPages() | ||
| 458 | { | ||
| 459 | #define n_pages ((unsigned)regp->hregs.x.rbx) | ||
| 460 | register unsigned handle; /* handle table index */ | ||
| 461 | register struct handle_ptr *hp; | ||
| 462 | |||
| 463 | if(handle_count == handle_table_size){ /* no more handles? */ | ||
| 464 | setAH(NO_MORE_HANDLES); /* nope */ | ||
| 465 | return; | ||
| 466 | } | ||
| 467 | |||
| 468 | if(n_pages > total_pages) { | ||
| 469 | setAH(NOT_ENOUGH_EXT_MEM); | ||
| 470 | return; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * loop through table to | ||
| 475 | * find available handle (page_index = NULL_PAGE) | ||
| 476 | */ | ||
| 477 | hp = (struct handle_ptr *)handle_table; | ||
| 478 | for(handle=0;handle<handle_table_size;handle++,hp++) | ||
| 479 | if(hp->page_index == NULL_PAGE) | ||
| 480 | break; /* found a free one */ | ||
| 481 | /* | ||
| 482 | * try and allocate pages | ||
| 483 | */ | ||
| 484 | if((hp->page_index=get_pages(n_pages,emmpt_start)) != NULL_PAGE) { | ||
| 485 | emmpt_start += n_pages; | ||
| 486 | setAH((unsigned char)EMMstatus); /* got them! */ | ||
| 487 | } | ||
| 488 | else { | ||
| 489 | setAH(NOT_ENOUGH_FREE_MEM); /* out of pages */ | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | |||
| 493 | hp->page_count=n_pages; /* set count */ | ||
| 494 | handle_count++; | ||
| 495 | setDX(handle); | ||
| 496 | |||
| 497 | /* AutoUpdate(); /* update status of Auto mode */ | ||
| 498 | |||
| 499 | } | ||
| 500 | #undef n_pages | ||
| 501 | |||
| 502 | /* | ||
| 503 | * deallocate pages | ||
| 504 | * parameters: | ||
| 505 | * dx -- handle | ||
| 506 | * | ||
| 507 | * free up the pages and handle table entry associated | ||
| 508 | * with this handle | ||
| 509 | * | ||
| 510 | * 05/09/88 ISP Updated for MEMM. Pulled out free_page routine and | ||
| 511 | * added support for handle name blanking. | ||
| 512 | */ | ||
| 513 | DeallocatePages() | ||
| 514 | { | ||
| 515 | #define handle ((unsigned)regp->hregs.x.rdx) | ||
| 516 | register struct handle_ptr *hp; | ||
| 517 | struct save_map *smp; /* save map table ptr */ | ||
| 518 | long *Name ; /* points to handle name entry to clear */ | ||
| 519 | |||
| 520 | if ( handle == 0 ) { /* Special handle, don't release */ | ||
| 521 | int savbx = regp->hregs.x.rbx; | ||
| 522 | regp->hregs.x.rbx = 0; | ||
| 523 | ReallocatePages(); | ||
| 524 | regp->hregs.x.rbx = savbx; | ||
| 525 | return; | ||
| 526 | } | ||
| 527 | |||
| 528 | if((hp=valid_handle(handle)) == NULL_HANDLE) | ||
| 529 | return; /* invalid handle, error code set */ | ||
| 530 | /* | ||
| 531 | * check for save area in use for this handle | ||
| 532 | */ | ||
| 533 | if( save_map[ (handle & 0x00FF) ].s_handle != (unsigned)NULL_HANDLE ) | ||
| 534 | { | ||
| 535 | setAH(SAVED_PAGE_DEALLOC); | ||
| 536 | return; | ||
| 537 | } | ||
| 538 | |||
| 539 | free_pages(hp); /*free the pages associated with handle*/ | ||
| 540 | hp->page_index = NULL_PAGE; /*and then free the handle*/ | ||
| 541 | hp->page_count = 0; /*bookkeeping*/ | ||
| 542 | Name = (long *)Handle_Name_Table[handle & 0xFF]; | ||
| 543 | *(Name+1) = *(Name) = 0L; /* zero the eight byte name */ | ||
| 544 | handle_count--; /* one less active handle */ | ||
| 545 | |||
| 546 | /* AutoUpdate(); /* update status of Auto mode */ | ||
| 547 | setAH((unsigned char)EMMstatus); /* done */ | ||
| 548 | } | ||
| 549 | #undef handle | ||
| 550 | |||
| 551 | |||
| 552 | /* | ||
| 553 | * get emm version | ||
| 554 | * no parameters | ||
| 555 | * | ||
| 556 | * returns the version number of the emm driver | ||
| 557 | * | ||
| 558 | * 05/06/88 ISP No update needed for MEMM | ||
| 559 | */ | ||
| 560 | GetEMMVersion() | ||
| 561 | { | ||
| 562 | setAX( (EMMstatus<<8) | EMM_VERSION ); | ||
| 563 | } | ||
| 564 | |||
| 565 | /* | ||
| 566 | * Get EMM handle count | ||
| 567 | * no parameters | ||
| 568 | * | ||
| 569 | * return the number of active EMM handles | ||
| 570 | * | ||
| 571 | * 05/06/88 ISP No update needed for MEMM | ||
| 572 | */ | ||
| 573 | GetEMMHandleCount() | ||
| 574 | { | ||
| 575 | setBX(handle_count); | ||
| 576 | setAH((unsigned char)EMMstatus); | ||
| 577 | } | ||
| 578 | |||
| 579 | /* | ||
| 580 | * Get EMM handle pages | ||
| 581 | * parameters: | ||
| 582 | * dx -- handle | ||
| 583 | * | ||
| 584 | * return the number of pages allocated to specified handle in BX | ||
| 585 | * | ||
| 586 | * 05/09/88 ISP No update needed for MEMM | ||
| 587 | */ | ||
| 588 | GetEMMHandlePages() | ||
| 589 | { | ||
| 590 | #define handle ((unsigned)regp->hregs.x.rdx) | ||
| 591 | register struct handle_ptr *hp; | ||
| 592 | |||
| 593 | if((hp=valid_handle(handle))==NULL_HANDLE) /*valid handle? */ | ||
| 594 | return; /* no */ | ||
| 595 | setBX(hp->page_count); | ||
| 596 | setAH((unsigned char)EMMstatus); | ||
| 597 | } | ||
| 598 | |||
| 599 | /* | ||
| 600 | * Get All EMM Handle Pages | ||
| 601 | * parameters: | ||
| 602 | * es:di -- userptr | ||
| 603 | * | ||
| 604 | * fill out array of handle/size pairs | ||
| 605 | * | ||
| 606 | * 05/09/88 ISP Updated for MEMM (just removed upper byte of handle) | ||
| 607 | */ | ||
| 608 | GetAllEMMHandlePages() | ||
| 609 | { | ||
| 610 | unsigned far *u_ptr; | ||
| 611 | register struct handle_ptr *hp; | ||
| 612 | register unsigned h_index; | ||
| 613 | |||
| 614 | /* | ||
| 615 | * scan handle table and for each valid entry, | ||
| 616 | * copy handle and size to user array | ||
| 617 | */ | ||
| 618 | u_ptr = dest_addr(); | ||
| 619 | |||
| 620 | hp=handle_table; | ||
| 621 | for(h_index=0;h_index<handle_table_size;h_index++) | ||
| 622 | { | ||
| 623 | /* scan table for entries */ | ||
| 624 | if(hp->page_index != NULL_PAGE) /* valid entry? */ | ||
| 625 | { | ||
| 626 | *u_ptr++ = h_index; /* handle */ | ||
| 627 | *u_ptr++ = hp->page_count; /*# of pgs for handle*/ | ||
| 628 | } | ||
| 629 | hp++; /* next entry */ | ||
| 630 | } | ||
| 631 | setBX(handle_count); /* bx <-- handle count */ | ||
| 632 | setAH((unsigned char)EMMstatus); | ||
| 633 | } | ||
| 634 | |||
| 635 | /* | ||
| 636 | * Get Page Mapping Register I/O Port Array | ||
| 637 | * parameters: | ||
| 638 | es:di -- user array | ||
| 639 | * | ||
| 640 | * 05/09/88 ISP Function not supported | ||
| 641 | */ | ||
| 642 | GetPageMappingRegisterIOArray() | ||
| 643 | { | ||
| 644 | |||
| 645 | setAH(INVALID_FUNCTION); | ||
| 646 | } | ||
| 647 | |||
| 648 | /* | ||
| 649 | * Get Logical to Physical Page Translation Array | ||
| 650 | * parameters: | ||
| 651 | * es:di -- pointer to user array | ||
| 652 | * dx ----- EMM handle | ||
| 653 | * | ||
| 654 | * 05/09/88 ISP Function not supported | ||
| 655 | */ | ||
| 656 | GetLogicalToPhysicalPageTrans() | ||
| 657 | { | ||
| 658 | setAH(INVALID_FUNCTION); | ||
| 659 | } | ||
| 660 | \ No newline at end of file | ||