diff options
Diffstat (limited to 'v4.0/src/MEMM/MEMM')
68 files changed, 24959 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/MEMM/A20TRAP.ASM b/v4.0/src/MEMM/MEMM/A20TRAP.ASM new file mode 100644 index 0000000..2f7f377 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/A20TRAP.ASM | |||
| @@ -0,0 +1,528 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title A20TRAP.ASM - I/O trap handlers for watching the A20 line. | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: A20TRAP.ASM - I/O trap handlers for watching the A20 line. | ||
| 13 | ; | ||
| 14 | ; Version: 0.03 | ||
| 15 | ; | ||
| 16 | ; Date: June 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 07/03/86 0.03 From ChkDisA20 routine in VMINST. | ||
| 27 | ; | ||
| 28 | ;****************************************************************************** | ||
| 29 | ; | ||
| 30 | ; Functional Description: | ||
| 31 | ; This module contains the I/O trap handlers for the A20 line watching | ||
| 32 | ; logic. | ||
| 33 | ; | ||
| 34 | ; | ||
| 35 | ; COMMENTS: This module displays weaknesses due to carryover from previous | ||
| 36 | ; sources. A lot of the code here can be shifted to the LAST | ||
| 37 | ; segment. There is a duplication of routines for getting the a20 | ||
| 38 | ; state. (ISP) | ||
| 39 | ;****************************************************************************** | ||
| 40 | .lfcond ; list false conditionals | ||
| 41 | .386p | ||
| 42 | page | ||
| 43 | ;****************************************************************************** | ||
| 44 | ; P U B L I C D E C L A R A T I O N S | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; | ||
| 47 | public A20_Handler | ||
| 48 | public A20_Trap_Init | ||
| 49 | public EnableA20 | ||
| 50 | public DisableA20 | ||
| 51 | public togl_A20 | ||
| 52 | public get_a20_state | ||
| 53 | public estb_a20_state | ||
| 54 | public get_init_a20_state | ||
| 55 | |||
| 56 | |||
| 57 | ; | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; E X T E R N A L R E F E R E N C E S | ||
| 60 | ;****************************************************************************** | ||
| 61 | include VDMseg.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | ; | ||
| 64 | _DATA segment | ||
| 65 | ; (none) | ||
| 66 | _DATA ends | ||
| 67 | |||
| 68 | _TEXT segment | ||
| 69 | |||
| 70 | extrn PortTrap:near | ||
| 71 | |||
| 72 | _TEXT ends | ||
| 73 | page | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; L O C A L C O N S T A N T S | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; | ||
| 78 | FALSE equ 0 | ||
| 79 | TRUE equ not FALSE | ||
| 80 | |||
| 81 | YesLLdone equ 1 | ||
| 82 | KbdDataEnb equ 2 | ||
| 83 | |||
| 84 | A20CmdBit equ 02h ; high is enabled | ||
| 85 | A20DsbCmd equ 0DDh | ||
| 86 | A20EnbCmd equ 0DFh | ||
| 87 | |||
| 88 | KbdCmdPort equ 64h ; 8042 cmd port | ||
| 89 | KbdWrtData equ 0D1h ; Enable write to data port | ||
| 90 | KbdDataPort equ 60h ; 8042 data port | ||
| 91 | KbdStatusPort equ 64h ; 8042 cmd port | ||
| 92 | KbdBufFull equ 2 ; Buffer bull(data not received) status | ||
| 93 | |||
| 94 | ; equates for the state_a20 flag | ||
| 95 | |||
| 96 | A20_ON equ A20CmdBit ; | ||
| 97 | A20_OFF equ 0 ; | ||
| 98 | ; | ||
| 99 | ; equate for the bit which will toggle the state of | ||
| 100 | ; | ||
| 101 | WRAP_BIT equ 00100000h ; page table entry bit | ||
| 102 | ; | ||
| 103 | ;****************************************************************************** | ||
| 104 | ; S E G M E N T D E F I N I T I O N | ||
| 105 | ;****************************************************************************** | ||
| 106 | ; | ||
| 107 | |||
| 108 | ; | ||
| 109 | ; _DATA segment | ||
| 110 | ; | ||
| 111 | _DATA segment | ||
| 112 | |||
| 113 | KbdComd db 0 ; last CMD written to port 64h | ||
| 114 | state_a20 db 0 ; A20 line state: A20_ON is on, A20_OFF is off | ||
| 115 | |||
| 116 | _DATA ends | ||
| 117 | |||
| 118 | ; | ||
| 119 | page | ||
| 120 | ;------------------------------------------------------------------------------ | ||
| 121 | _TEXT segment | ||
| 122 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 123 | ; | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; L O C A L D A T A A R E A | ||
| 126 | ;****************************************************************************** | ||
| 127 | ; | ||
| 128 | |||
| 129 | ;****************************************************************************** | ||
| 130 | ; A20_Handler - I/O trap handler for Address line 20 modification | ||
| 131 | ; | ||
| 132 | ; ENTRY: Protected Mode Ring 0 | ||
| 133 | ; AL = byte to output to port. | ||
| 134 | ; BX == 2 * port address(either KbdDataPort or KbdCmdPort) | ||
| 135 | ; DX == 0 => Emulate input | ||
| 136 | ; <> 0 => Emulate output | ||
| 137 | ; DS = DGROUP | ||
| 138 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 139 | ; | ||
| 140 | ; EXIT: | ||
| 141 | ; CLC => I/O emulated. | ||
| 142 | ; STC => I/O NOT emulated. | ||
| 143 | ; | ||
| 144 | ; USED: BX,Flags | ||
| 145 | ; STACK: | ||
| 146 | ;------------------------------------------------------------------------------ | ||
| 147 | A20_Handler proc near | ||
| 148 | or dx,dx ;Q: Output ? | ||
| 149 | jnz A20_Write ; Y: check for write to output port | ||
| 150 | stc ; N: don't bother to emulate it | ||
| 151 | ret | ||
| 152 | A20_Write: | ||
| 153 | cmp bx,KbdDataPort*2 ;Q: Keyboard data port? | ||
| 154 | jne Kbd_C_Handler ; N: Go handle Kybd Command output | ||
| 155 | ; Y: Go handle Kybd Data output | ||
| 156 | |||
| 157 | ; keyboard data write | ||
| 158 | Kbd_D_Dwrite: | ||
| 159 | cmp [KbdComd],KbdWrtData ;Q: write to output port? | ||
| 160 | mov [KbdComd],0 ; data port write => no CMD | ||
| 161 | je Kbd_D_out ; Y: filter client's data | ||
| 162 | stc ; N: don't bother to emulate it | ||
| 163 | ret | ||
| 164 | ; | ||
| 165 | ; here if Output Port write | ||
| 166 | ; | ||
| 167 | Kbd_D_out: | ||
| 168 | push ax ; Set A20 cmd bit | ||
| 169 | call check_a20_togl ; do we need to toggle the | ||
| 170 | ; the a20 state | ||
| 171 | jz skip_togl ; N: Skip routine to toggle | ||
| 172 | call togl_a20 | ||
| 173 | skip_togl: | ||
| 174 | or al, A20CmdBit ; to leave A20 enabled | ||
| 175 | out KbdDataPort,al ; "emulate" it | ||
| 176 | pop ax ; restore client's byte | ||
| 177 | clc ; emulated | ||
| 178 | ret | ||
| 179 | |||
| 180 | ;Output to Keyboard command port | ||
| 181 | Kbd_C_Handler: | ||
| 182 | ; | ||
| 183 | mov [KbdComd],al ; Y: save new port 64 byte | ||
| 184 | stc ; don't bother to emulate it | ||
| 185 | ret | ||
| 186 | ; | ||
| 187 | A20_Handler endp | ||
| 188 | |||
| 189 | |||
| 190 | ;****************************************************************************** | ||
| 191 | ; A20_Trap_Init - turn on I/O bit map trapping for A20 line watching | ||
| 192 | ; | ||
| 193 | ; ENTRY: DS -> DGROUP - real,virtual, or protected mode | ||
| 194 | ; ES -> TSS segment | ||
| 195 | ; IOTrap_Tab already has address of A20_Handler for KbdDataPort and | ||
| 196 | ; KbdCmdPort | ||
| 197 | ; | ||
| 198 | ; EXIT: IO_BitMap Updated to trap ports used to change A20 line | ||
| 199 | ; | ||
| 200 | ; USED: AX,Flags | ||
| 201 | ; STACK: | ||
| 202 | ;------------------------------------------------------------------------------ | ||
| 203 | A20_Trap_Init proc near | ||
| 204 | ; | ||
| 205 | ; reset flag | ||
| 206 | ; | ||
| 207 | mov [KbdComd],0 | ||
| 208 | ; | ||
| 209 | ; Set IOBM traps to look for client's disabling of the A20 line | ||
| 210 | ; | ||
| 211 | mov bh, 80h ; set every 1k | ||
| 212 | mov ax, KbdDataPort | ||
| 213 | call PortTrap ; set traps on keyboard ports | ||
| 214 | mov ax, KbdCmdPort ; in case client | ||
| 215 | call PortTrap ; tries to disable A20 | ||
| 216 | ret | ||
| 217 | ; | ||
| 218 | A20_Trap_Init endp | ||
| 219 | ; | ||
| 220 | ;*****************************************************************************; | ||
| 221 | ;*** EnableA20 - switch 20th address line ; | ||
| 222 | ; ; | ||
| 223 | ; This routine is used to enable the 20th address line in ; | ||
| 224 | ; the system. ; | ||
| 225 | ; ; | ||
| 226 | ; In general when in real mode we want the A20 line disabled, ; | ||
| 227 | ; when in protected mode enabled. However if there is no high ; | ||
| 228 | ; memory installed we can optimise out unnecessary switching ; | ||
| 229 | ; of the A20 line. Unfortunately the PC/AT ROM does not allow ; | ||
| 230 | ; us to completely decouple mode switching the 286 from gating ; | ||
| 231 | ; the A20 line. ; | ||
| 232 | ; ; | ||
| 233 | ; In real mode we would want A20 enabled if we need to access ; | ||
| 234 | ; high memory, for example in a device driver. We want it ; | ||
| 235 | ; disabled while running arbitrary applications because they ; | ||
| 236 | ; may rely on the 1 meg address wrap feature which having the ; | ||
| 237 | ; A20 line off provides. ; | ||
| 238 | ; ; | ||
| 239 | ; This code is largely duplicated from the PC/AT ROM BIOS. ; | ||
| 240 | ; See Module "BIOS1" on page 5-155 of the PC/AT tech ref. ; | ||
| 241 | ; ; | ||
| 242 | ; ENTRY none ;ds = DGROUP ; | ||
| 243 | ; EXIT A20 line enabled ; | ||
| 244 | ; USES ax, flags modified ; | ||
| 245 | ; ; | ||
| 246 | ; WARNING: ; | ||
| 247 | ; ; | ||
| 248 | ; The performance characteristics of these routines ; | ||
| 249 | ; are not well understood. There may be worst case ; | ||
| 250 | ; scenarios where the routine could take a relatively ; | ||
| 251 | ; long time to complete. ; | ||
| 252 | ; ; | ||
| 253 | ; TO BE ADDED: ; | ||
| 254 | ; ; | ||
| 255 | ; 8042 error handling ; | ||
| 256 | ;*****************************************************************************; | ||
| 257 | EnableA20 proc near | ||
| 258 | mov ah,0dfh ; code for enable | ||
| 259 | jmp a20common ; jump to common code | ||
| 260 | |||
| 261 | EnableA20 endp | ||
| 262 | |||
| 263 | ;*****************************************************************************; | ||
| 264 | ;*** DisableA20 - switch 20th address line ; | ||
| 265 | ; ; | ||
| 266 | ; This routine is used to disable the 20th address line in ; | ||
| 267 | ; the system. ; | ||
| 268 | ; ; | ||
| 269 | ; ENTRY none ;ds = DATA ; | ||
| 270 | ; EXIT A20 line disabled ; | ||
| 271 | ; [state_a20] = 0 ; | ||
| 272 | ; USES ax, flags modified ; | ||
| 273 | ;*****************************************************************************; | ||
| 274 | |||
| 275 | DisableA20 proc near | ||
| 276 | mov ah,0ddh ; code for disable | ||
| 277 | jmp a20common ; jump to common code | ||
| 278 | |||
| 279 | DisableA20 endp | ||
| 280 | |||
| 281 | |||
| 282 | a20common proc near | ||
| 283 | |||
| 284 | ; This is entered via a jmp from one of the two procedural | ||
| 285 | ; entry points above. | ||
| 286 | |||
| 287 | call empty_8042 ; ensure 8042 input buffer empty | ||
| 288 | jnz com1 ; 8042 error return | ||
| 289 | mov al,0d1h ; 8042 cmd to write output port | ||
| 290 | out KbdCmdPort,al ; send cmd to 8042 | ||
| 291 | call empty_8042 ; wait for 8042 to accept cmd | ||
| 292 | jnz com1 ; 8042 error return | ||
| 293 | mov al,ah ; 8042 port data | ||
| 294 | out KbdDataPort,al ; output port data to 8042 | ||
| 295 | call empty_8042 | ||
| 296 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 297 | ; | ||
| 298 | ; AST P/386 needs the delay for their | ||
| 299 | ; A20 switch settle. If not, it won't work ! | ||
| 300 | ; PC (10/03/88) | ||
| 301 | ; | ||
| 302 | push cx | ||
| 303 | mov cx, 0100h | ||
| 304 | ASTloop: | ||
| 305 | loop ASTloop | ||
| 306 | pop cx | ||
| 307 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 308 | |||
| 309 | com1: | ||
| 310 | ret | ||
| 311 | a20common endp | ||
| 312 | |||
| 313 | ;*****************************************************************************; | ||
| 314 | ;*** empty_8042 - wait for 8042 input buffer to drain ; | ||
| 315 | ; ; | ||
| 316 | ; ENTRY none ; | ||
| 317 | ; EXIT al=0, z=0 => 8042 input buffer empty ; | ||
| 318 | ; al=2, z=1 => timeout, input buffer full ; | ||
| 319 | ; USES none ; | ||
| 320 | ;*****************************************************************************; | ||
| 321 | empty_8042 proc near | ||
| 322 | push cx ; save it | ||
| 323 | sub cx,cx ; cx = 0, timeout loop counter | ||
| 324 | emp1: | ||
| 325 | in al,KbdStatusPort ; read 8042 status port | ||
| 326 | and al,KbdBufFull ; test buffer full bit | ||
| 327 | loopnz emp1 | ||
| 328 | pop cx | ||
| 329 | ret | ||
| 330 | empty_8042 endp | ||
| 331 | |||
| 332 | ;*****************************************************************************; | ||
| 333 | ;*** check_a20_togl - check if a20 state emulated needs to be toggled ; | ||
| 334 | ; ; | ||
| 335 | ; ENTRY [state_a20] = A20 emulated state ; | ||
| 336 | ; al = byte to output to kbd data port ; | ||
| 337 | ; EXIT Z set if A20 not to be toggled ; | ||
| 338 | ; clear if A20 to be toggled ; | ||
| 339 | ; USES Flags ; | ||
| 340 | ; ; | ||
| 341 | ;*****************************************************************************; | ||
| 342 | check_a20_togl proc near | ||
| 343 | ; | ||
| 344 | push ax | ||
| 345 | and al,A20CmdBit ; make all other bits 0 | ||
| 346 | xor al,[state_a20] ; does the state of the a20 bit match | ||
| 347 | ; Y: then Z is set | ||
| 348 | ; N: then Z is not set | ||
| 349 | pop ax | ||
| 350 | ret | ||
| 351 | ; | ||
| 352 | check_a20_togl endp | ||
| 353 | |||
| 354 | |||
| 355 | ;*****************************************************************************; | ||
| 356 | ;*** get_a20_state - see if virtualised a20 is enabled or not ; | ||
| 357 | ; ; | ||
| 358 | ; ENTRY [state_a20] = A20 emulated state ; | ||
| 359 | ; ; | ||
| 360 | ; EXIT ZF set if A20 disabled ; | ||
| 361 | ; ZF not set if A20 enabled ; | ||
| 362 | ; ; | ||
| 363 | ; USES Flags ; | ||
| 364 | ;*****************************************************************************; | ||
| 365 | |||
| 366 | get_a20_state proc near | ||
| 367 | ; | ||
| 368 | test [state_a20], A20_ON | ||
| 369 | ret | ||
| 370 | get_a20_state endp | ||
| 371 | |||
| 372 | |||
| 373 | ;*****************************************************************************; | ||
| 374 | ;*** togl_A20 - toggle emulated A20 state. ; | ||
| 375 | ; ; | ||
| 376 | ; ENTRY [state_a20] = A20 emulated state ; | ||
| 377 | ; PROTECTED MODE ONLY ; | ||
| 378 | ; DS:DGROUP ; | ||
| 379 | ; ; | ||
| 380 | ; EXIT [state_a20] toggled ; | ||
| 381 | ; page table entries for the 1M --> 1M + 64k area toggled ; | ||
| 382 | ; ; | ||
| 383 | ; USES Flags ; | ||
| 384 | ; ; | ||
| 385 | ; ; | ||
| 386 | ;*****************************************************************************; | ||
| 387 | togl_A20 proc near | ||
| 388 | ; | ||
| 389 | push es | ||
| 390 | push di | ||
| 391 | push cx | ||
| 392 | push eax | ||
| 393 | ; | ||
| 394 | ; get addressability to page table | ||
| 395 | ; | ||
| 396 | push PAGET_GSEL | ||
| 397 | pop es | ||
| 398 | ; | ||
| 399 | ; and offset into entries for the 64k block at 1M | ||
| 400 | ; | ||
| 401 | mov di,100h*4 ; 1024k/4k = 256 entries, each 4 bytes long | ||
| 402 | mov cx,10h ; 64k/4k = 16 entries | ||
| 403 | cld | ||
| 404 | ; | ||
| 405 | ; for all the entries flip the bit which will make the entries either wrap | ||
| 406 | ; around for 1M-1M+64k to either 1M-1M+64k or 0-64k. This bit is the 1M bit | ||
| 407 | ; in the base address. | ||
| 408 | ; | ||
| 409 | w64_loop: | ||
| 410 | xor dword ptr es:[di], WRAP_BIT | ||
| 411 | add di,4 | ||
| 412 | loop w64_loop | ||
| 413 | ; | ||
| 414 | ; flush the tlb | ||
| 415 | ; | ||
| 416 | mov eax,cr3 | ||
| 417 | mov cr3,eax | ||
| 418 | ; | ||
| 419 | ; toggle a20 state | ||
| 420 | ; | ||
| 421 | xor [state_a20],A20_ON | ||
| 422 | ; | ||
| 423 | ; restore the registers | ||
| 424 | ; | ||
| 425 | pop eax | ||
| 426 | pop cx | ||
| 427 | pop di | ||
| 428 | pop es | ||
| 429 | ret | ||
| 430 | ; | ||
| 431 | togl_A20 endp | ||
| 432 | |||
| 433 | |||
| 434 | |||
| 435 | _TEXT ends ; end of segment | ||
| 436 | |||
| 437 | LAST segment | ||
| 438 | |||
| 439 | assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 440 | |||
| 441 | |||
| 442 | ;****************************************************************************** | ||
| 443 | ;***estb_a20_state ; | ||
| 444 | ; ; | ||
| 445 | ; since we are fixing the a20 state to be always enabled we need to implement ; | ||
| 446 | ; a logical a20 state independent of the physical one. this routine inits ; | ||
| 447 | ; this state. we do this comparing 3 double words at 0:80 and 1M:80. if these; | ||
| 448 | ; compare the a20 is disabled thus causing a wraparound. ; | ||
| 449 | ; ; | ||
| 450 | ; INPUTS: ; | ||
| 451 | ; ; | ||
| 452 | ; OUTPUTS: [state_a20] .. A20_ON if a20 is on currently ; | ||
| 453 | ; .. A20_OFF if a20 is off currently ; | ||
| 454 | ; ; | ||
| 455 | ; USES: flags ; | ||
| 456 | ; ; | ||
| 457 | ; AUTHOR: ISP. Shifted in from smartdrv sources. 8/29/88. ; | ||
| 458 | ; ; | ||
| 459 | ;*****************************************************************************; | ||
| 460 | ; A20 address line state determination addresses | ||
| 461 | ; | ||
| 462 | low_mem label dword | ||
| 463 | dw 20h*4 | ||
| 464 | dw 0 | ||
| 465 | |||
| 466 | high_mem label dword | ||
| 467 | dw 20h*4 + 10h | ||
| 468 | dw 0ffffh | ||
| 469 | |||
| 470 | estb_a20_state proc near | ||
| 471 | push cx | ||
| 472 | push ds | ||
| 473 | push es | ||
| 474 | push si | ||
| 475 | push di | ||
| 476 | ; | ||
| 477 | ; initialise a20 to off | ||
| 478 | ; | ||
| 479 | mov [state_a20],A20_OFF | ||
| 480 | ; | ||
| 481 | ; compare 3 dwords at 0:80h and 1M:80h. if these are equal then | ||
| 482 | ; we can assume that a20 is off | ||
| 483 | ; | ||
| 484 | lds si,cs:low_mem | ||
| 485 | ASSUME DS:NOTHING | ||
| 486 | les di,cs:high_mem | ||
| 487 | ASSUME ES:NOTHING | ||
| 488 | mov cx,3 | ||
| 489 | cld | ||
| 490 | repe cmpsd | ||
| 491 | pop di | ||
| 492 | pop si | ||
| 493 | pop es | ||
| 494 | pop ds | ||
| 495 | ASSUME DS:DGROUP,ES:DGROUP | ||
| 496 | jcxz not_enabled | ||
| 497 | ; | ||
| 498 | ; a20 is on | ||
| 499 | ; | ||
| 500 | mov [state_a20],A20_ON | ||
| 501 | not_enabled: | ||
| 502 | pop cx | ||
| 503 | ret | ||
| 504 | estb_a20_state endp | ||
| 505 | |||
| 506 | ;*****************************************************************************; | ||
| 507 | ;*** get_init_a20_state - see if virtualised a20 is enabled or not ; | ||
| 508 | ; ; | ||
| 509 | ; ENTRY [state_a20] = A20 state at startup ; | ||
| 510 | ; ; | ||
| 511 | ; EXIT ZF set if A20 disabled ; | ||
| 512 | ; ZF not set if A20 enabled ; | ||
| 513 | ; ; | ||
| 514 | ; USES Flags ; | ||
| 515 | ;*****************************************************************************; | ||
| 516 | |||
| 517 | ASSUME DS:DGROUP,ES:NOTHING | ||
| 518 | |||
| 519 | get_init_a20_state proc near | ||
| 520 | ; | ||
| 521 | test [state_a20], A20_ON | ||
| 522 | ret | ||
| 523 | get_init_a20_state endp | ||
| 524 | |||
| 525 | LAST ends | ||
| 526 | |||
| 527 | end ; end of module | ||
| 528 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM b/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM new file mode 100644 index 0000000..430f849 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ALLOCMEM.ASM | |||
| @@ -0,0 +1,567 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title ALLOCMEM - allocate memory for EMM Pages Pool | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: AllocMem - allocate memory for EMM Pages Pool | ||
| 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 | ; 05/24/86 Original | ||
| 27 | ; 06/28/86 0.02 code read changes to various routines | ||
| 28 | ; 07/05/86 0.04 Changes due to segment re-org | ||
| 29 | ; 07/06/86 0.04 Made EXT_RES a define | ||
| 30 | ; 07/06/86 0.04 Changed to DGROUP assume | ||
| 31 | ; 07/10/86 0.05 added NOHIMEM flag | ||
| 32 | ; 06/02/88 pc change from VDISK allocation to INT-15 method | ||
| 33 | ; 07/26/88 isp completed work in changing over to int15 alloc | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ; Functional Description: | ||
| 37 | ; This module allocates the pool of memory to be used for the pool of | ||
| 38 | ; EMM pages. The pool of memory is allocated from "high" extended | ||
| 39 | ; memory (located in the 15-16 Meg range)and from "regular" extended memory | ||
| 40 | ; (starting at 1 Meg). This module attempts to allocate high memory first, | ||
| 41 | ; then extended memory. When allocating memory from either area, the memory | ||
| 42 | ; is allocated in 16k byte blocks which are aligned on a physical 4k boundary. | ||
| 43 | ; This module attempts to allocate extended memory using the int15 allocation | ||
| 44 | ; scheme. | ||
| 45 | ; | ||
| 46 | ; NOTE: if this module is compiled with NOHIMEM defined, then | ||
| 47 | ; this code will not attempt to use the OEM specific | ||
| 48 | ; "high" memory. | ||
| 49 | ; | ||
| 50 | ;****************************************************************************** | ||
| 51 | .lfcond | ||
| 52 | .386p | ||
| 53 | ; | ||
| 54 | ; | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; P U B L I C D E C L A R A T I O N S | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; | ||
| 59 | public AllocMem | ||
| 60 | public DeallocMem | ||
| 61 | public xbase_addr_l ; data publics | ||
| 62 | public xbase_addr_h | ||
| 63 | public ext_size | ||
| 64 | public sys_size | ||
| 65 | |||
| 66 | page | ||
| 67 | ;****************************************************************************** | ||
| 68 | ; L O C A L C O N S T A N T S | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; | ||
| 71 | include vdmseg.inc | ||
| 72 | include vdmsel.inc | ||
| 73 | include emm386.inc | ||
| 74 | include driver.equ | ||
| 75 | include driver.str | ||
| 76 | include romxbios.equ | ||
| 77 | include desc.inc | ||
| 78 | include ascii_sm.equ | ||
| 79 | include oemdep.inc | ||
| 80 | include emmdef.inc | ||
| 81 | ; | ||
| 82 | EXT_RES equ 10h ; must be a power of 2. | ||
| 83 | ; | ||
| 84 | GET_VER equ 30h ; get dos version number | ||
| 85 | MSDOS equ 21h ; DOS interrupt | ||
| 86 | ; | ||
| 87 | FALSE equ 0 | ||
| 88 | TRUE equ not FALSE | ||
| 89 | |||
| 90 | ;****************************************************************************** | ||
| 91 | ; E X T E R N A L R E F E R E N C E S | ||
| 92 | ;****************************************************************************** | ||
| 93 | ; | ||
| 94 | _DATA segment | ||
| 95 | |||
| 96 | extrn dos_version:byte | ||
| 97 | extrn pool_size:word | ||
| 98 | extrn msg_flag:word | ||
| 99 | |||
| 100 | ifndef NOHIMEM | ||
| 101 | extrn hi_size:word ; size of hi memory in kbytes | ||
| 102 | extrn hi_alloc:word ; hi memory allocated | ||
| 103 | extrn hisys_alloc:word ; hi system memory allocated | ||
| 104 | ; in 4k byte blocks | ||
| 105 | endif | ||
| 106 | |||
| 107 | _DATA ends | ||
| 108 | |||
| 109 | |||
| 110 | LAST segment | ||
| 111 | extrn mappable_segs:byte ; mappable segment map | ||
| 112 | extrn set_ext:near ; routine to set amount of ext mem | ||
| 113 | ; reported by int15 handler | ||
| 114 | extrn memreq:near ; memory requirements for move | ||
| 115 | extrn pool_initialise:near ; initialise the pool of extended | ||
| 116 | ; memory | ||
| 117 | |||
| 118 | ifndef NOHIMEM | ||
| 119 | extrn hbuf_chk:near | ||
| 120 | extrn HiAlloc:near | ||
| 121 | extrn HiMod:near | ||
| 122 | endif | ||
| 123 | LAST ends | ||
| 124 | ; | ||
| 125 | page | ||
| 126 | ;****************************************************************************** | ||
| 127 | ; S E G M E N T D E F I N I T I O N | ||
| 128 | ;****************************************************************************** | ||
| 129 | |||
| 130 | page | ||
| 131 | ;****************************************************************************** | ||
| 132 | ; Data segment | ||
| 133 | ;****************************************************************************** | ||
| 134 | _DATA segment | ||
| 135 | ASSUME CS:DGROUP,DS:DGROUP | ||
| 136 | |||
| 137 | xbase_addr_l dw 0000h ; 24 bit address of beginning of | ||
| 138 | xbase_addr_h db 10h ; extended mem pool of EMM pages. (1M initially) | ||
| 139 | ext_size dw 0 ; size of extended memory allocated in kb | ||
| 140 | sys_size dw 0 ; size of system memory from 4000h in emm pool | ||
| 141 | total_mem dw 0 ; size of extended memory available at any moment | ||
| 142 | avail_mem dw 0 ; total size (hi+ext) available for MEMM | ||
| 143 | ; | ||
| 144 | |||
| 145 | _DATA ends | ||
| 146 | |||
| 147 | |||
| 148 | ;****************************************************************************** | ||
| 149 | ; | ||
| 150 | ; Code Segment | ||
| 151 | ; | ||
| 152 | ;****************************************************************************** | ||
| 153 | ; | ||
| 154 | LAST segment | ||
| 155 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 156 | |||
| 157 | page | ||
| 158 | ;****************************************************************************** | ||
| 159 | ; | ||
| 160 | ; AllocMem Allocate Extended memory for MEMM using the int15 | ||
| 161 | ; method of allocating extended memory. | ||
| 162 | ; | ||
| 163 | ; description: | ||
| 164 | ; This routine attempts to get the requested extended memory | ||
| 165 | ; from two sources: a) the himem area (just below 16M) first | ||
| 166 | ; and if not enough b) extended memory. Extended memory is | ||
| 167 | ; allocated using the int15 scheme. We do not care for | ||
| 168 | ; compatibility with vdisk. The memory we allocate either in | ||
| 169 | ; himem area or in extended memory must start at a 4k boundary | ||
| 170 | ; because we are using them as pages. | ||
| 171 | ; | ||
| 172 | ; entry: DS pts to DGROUP | ||
| 173 | ; DGROUP:[pool_size] = mem size requested (kbytes) | ||
| 174 | ; | ||
| 175 | ; exit: If extended memory pool space is not available then | ||
| 176 | ; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit. | ||
| 177 | ; | ||
| 178 | ; | ||
| 179 | ; used: none | ||
| 180 | ; | ||
| 181 | ; stack: | ||
| 182 | ; | ||
| 183 | ; modified: ISP 07/26/88 Changed to a simple check for availability | ||
| 184 | ; of hi / ext memory and allocation of | ||
| 185 | ; of appropriate amounts of each. | ||
| 186 | ; | ||
| 187 | ; | ||
| 188 | ;****************************************************************************** | ||
| 189 | ; | ||
| 190 | AllocMem proc near | ||
| 191 | ; | ||
| 192 | push ax | ||
| 193 | push bx | ||
| 194 | push cx | ||
| 195 | push dx | ||
| 196 | push es | ||
| 197 | |||
| 198 | |||
| 199 | ; | ||
| 200 | ; 1. Check available hi/extended memory | ||
| 201 | ; | ||
| 202 | AM_getmem: | ||
| 203 | call xbuf_chk | ||
| 204 | test [msg_flag],MEM_ERR_MSG ;Q: memory error found ? | ||
| 205 | jz AM_nba ; N: continue with allocation | ||
| 206 | jmp AM_exit ; Y: exit | ||
| 207 | ; | ||
| 208 | ; 2. Allocate extended memory | ||
| 209 | ; | ||
| 210 | AM_nba: | ||
| 211 | call ExtAlloc ; alloc ext mem | ||
| 212 | |||
| 213 | ifndef NOHIMEM ; if HI memory in this model | ||
| 214 | ; | ||
| 215 | ; 3. Allocate Hi memory | ||
| 216 | ; | ||
| 217 | AM_halloc: | ||
| 218 | call HiAlloc ; Allocate hi memory | ||
| 219 | jnc AM_exit ; no error | ||
| 220 | or [msg_flag],MEM_ERR_MSG ; memory error | ||
| 221 | endif | ||
| 222 | |||
| 223 | ; | ||
| 224 | ; 4. Allocate system memory | ||
| 225 | ; | ||
| 226 | call SysAlloc | ||
| 227 | ; | ||
| 228 | AM_exit: | ||
| 229 | pop es | ||
| 230 | pop dx | ||
| 231 | pop cx | ||
| 232 | pop bx | ||
| 233 | pop ax | ||
| 234 | ret | ||
| 235 | AllocMem endp ; End of procedure | ||
| 236 | ; | ||
| 237 | page | ||
| 238 | ;****************************************************************************** | ||
| 239 | ; | ||
| 240 | ; DeallocMem Deallocate Extended memory for MEMM using the int15 | ||
| 241 | ; method of allocating extended memory. Note that since | ||
| 242 | ; we call this routine when we haven't already installed tc.) | ||
| 243 | ; the int15 handler we really don't need to do anything | ||
| 244 | ; as far as the regular extended memory is concerned. We | ||
| 245 | ; only need to deallocate hi memory if allocated. | ||
| 246 | ; | ||
| 247 | ; entry: DS pts to DGROUP | ||
| 248 | ; DGROUP:[hi_alloc] amount of hi memory to deallocate | ||
| 249 | ; | ||
| 250 | ; used: none | ||
| 251 | ; | ||
| 252 | ; stack: | ||
| 253 | ; | ||
| 254 | ; modif: 7/26/88 ISP Removed VDISK deallocation of extended memory | ||
| 255 | ;****************************************************************************** | ||
| 256 | ; | ||
| 257 | DeallocMem proc near | ||
| 258 | push ax | ||
| 259 | push bx | ||
| 260 | push cx | ||
| 261 | push dx | ||
| 262 | push si | ||
| 263 | push es | ||
| 264 | ; | ||
| 265 | ifndef NOHIMEM ; if high memory in this model | ||
| 266 | mov ax,[hi_alloc] ; get hi memory to deallocate | ||
| 267 | or ax,ax ; q: did we ever get any? | ||
| 268 | jz deall_hisys ; n: check hi system memory | ||
| 269 | neg ax ; # of 16 byte pieces to remove | ||
| 270 | mov [hi_alloc],0 ; make sure we never do it again | ||
| 271 | deall_hisys: | ||
| 272 | mov bx,[hisys_alloc] ; get hi system memory to deallocate | ||
| 273 | neg bx ; update by a negative amount | ||
| 274 | add bx,ax ; q: any hi or hisys to deallocate? | ||
| 275 | jz deall_ext ; n: don't waste our time doing it | ||
| 276 | sub bx,ax ; y: straighten our regs out | ||
| 277 | mov [hisys_alloc],0 ; make sure we don't do it again | ||
| 278 | call HImod ; modify memory. ignore any errors | ||
| 279 | deall_ext: | ||
| 280 | ; | ||
| 281 | endif ; end of conditional | ||
| 282 | pop es | ||
| 283 | pop si | ||
| 284 | pop dx | ||
| 285 | pop cx | ||
| 286 | pop bx | ||
| 287 | pop ax | ||
| 288 | ; | ||
| 289 | ret | ||
| 290 | DeallocMem endp | ||
| 291 | ; | ||
| 292 | page | ||
| 293 | ;****************************************************************************** | ||
| 294 | ; | ||
| 295 | ; xbuf_chk Extended memory pool check. | ||
| 296 | ; Check 1) for previously loaded MEMM,VDISKs in extended memory | ||
| 297 | ; 2) available memory pool space. (hi memory and extended) | ||
| 298 | ; | ||
| 299 | ; entry: DS = DGROUP | ||
| 300 | ; DGROUP:[pool_size] = mem size requested (kbytes) | ||
| 301 | ; | ||
| 302 | ; | ||
| 303 | ; exit: If hi memory pool space is available then | ||
| 304 | ; | ||
| 305 | ; DGROUP:[hi_size] = hi memory size allocated (kbytes). | ||
| 306 | ; | ||
| 307 | ; If extended memory pool space is necessary and available then | ||
| 308 | ; | ||
| 309 | ; DGROUP:[xbase_addr_h] and DGROUP:[xbase_addr_l] contain the | ||
| 310 | ; starting 24-bit address of MEMM extended memory pool. | ||
| 311 | ; | ||
| 312 | ; DGROUP:[pool_size] = mem size ALLOCATED (kbytes) | ||
| 313 | ; DGROUP:[total_mem] = total extended memory left after allocation | ||
| 314 | ; DGROUP:[avail_mem] = available memory for MEMM. | ||
| 315 | ; DGROUP:[ext_size] = extended memory size allocated (kbytes) | ||
| 316 | ; | ||
| 317 | ; If hi/extended memory pool space is not available then | ||
| 318 | ; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit. | ||
| 319 | ; | ||
| 320 | ; used: none | ||
| 321 | ; | ||
| 322 | ; stack: | ||
| 323 | ; | ||
| 324 | ; modified: ISP 07/26/88 int15 allocation requires different check | ||
| 325 | ; on extended memory. substancial rewrite. | ||
| 326 | ;****************************************************************************** | ||
| 327 | ; | ||
| 328 | xbuf_chk proc near | ||
| 329 | ; | ||
| 330 | push ax | ||
| 331 | push bx | ||
| 332 | push cx | ||
| 333 | push dx | ||
| 334 | push di | ||
| 335 | ; | ||
| 336 | ; determine amount of extended memory and store it in total_mem | ||
| 337 | ; | ||
| 338 | mov ah,EXT_MEM ; function request - ext mem data | ||
| 339 | clc ; clear carry flag | ||
| 340 | int XBIOS ;Q: extended memory supported ? | ||
| 341 | ; | ||
| 342 | jnc store_ext ; Y: go to store the amount got | ||
| 343 | xor ax,ax ; N: Assume zero extended memory | ||
| 344 | store_ext: | ||
| 345 | mov [total_mem],ax | ||
| 346 | ; | ||
| 347 | ifndef NOHIMEM ; if high memory in this model | ||
| 348 | ; | ||
| 349 | ; check for hi memory | ||
| 350 | ; | ||
| 351 | call hbuf_chk ; get available hi memory in AX | ||
| 352 | jc xb_NoHiMem | ||
| 353 | mov [hi_size],ax ; save it | ||
| 354 | mov [avail_mem],ax ; update available memory | ||
| 355 | xb_NoHiMem: | ||
| 356 | mov ax,[pool_size] | ||
| 357 | cmp ax,[hi_size] ; q: enough? | ||
| 358 | ja get_ext ; n: try extended memory | ||
| 359 | mov [hi_size],ax ; y: just use enough | ||
| 360 | jmp x_buf_exit ; and exit | ||
| 361 | endif | ||
| 362 | |||
| 363 | get_ext: | ||
| 364 | mov ax,[total_mem] ; get size of extended memory available | ||
| 365 | ; Y: how much there ? | ||
| 366 | ; | ||
| 367 | ; we have to reserve enough memory here to ship the segments up hi. | ||
| 368 | ; | ||
| 369 | call memreq ; get memory requirements for our o | ||
| 370 | ; our grand operation in cx in K | ||
| 371 | cmp ax,cx ; lets see if we can satisfy | ||
| 372 | jbe x_buf_no_install ; if not we shan't install memm | ||
| 373 | |||
| 374 | push ax | ||
| 375 | sub ax,cx | ||
| 376 | cmp ax,64 + 64 ; we should try to leave enough memory | ||
| 377 | ; for himem and atleast four pages of | ||
| 378 | ; expanded memory. | ||
| 379 | pop ax | ||
| 380 | jbe x_buf_no_install ; if we don't have enough for this we | ||
| 381 | ; shouldn't install memm | ||
| 382 | ; | ||
| 383 | ; we can now get memory to shift things up. and intialise the manager of | ||
| 384 | ; this pool. | ||
| 385 | ; | ||
| 386 | sub ax,cx ; ax = start of this pool as an offset | ||
| 387 | ; in K from 1M | ||
| 388 | ; cx = size in K of this pool | ||
| 389 | call pool_initialise ; intialise the pool | ||
| 390 | or ax,ax ;Q: any extended memory ? | ||
| 391 | jz x_buf_2 ; N: If none go to set buf adj or no | ||
| 392 | ; memory error | ||
| 393 | ; ; Y: continue to process | ||
| 394 | ; | ||
| 395 | mov bx,[pool_size] ; get size requested | ||
| 396 | ; | ||
| 397 | ifndef NOHIMEM ; if high memory in this model | ||
| 398 | sub bx,[hi_size] ; adjust by the size already allocated | ||
| 399 | endif ; from the high memory | ||
| 400 | |||
| 401 | and ax,0fff0h ; round to 16k boundary | ||
| 402 | ; | ||
| 403 | ; it is necessary to support himem. So if we have a 64k block at 1M we | ||
| 404 | ; should leave it for himem. The himem we are talking about here is the | ||
| 405 | ; EMS 4.1 standard himem at 1M | ||
| 406 | ; | ||
| 407 | ; initialise reserved memory for himem | ||
| 408 | ; | ||
| 409 | xor cx,cx ; amount reserved for himem | ||
| 410 | ; | ||
| 411 | ; see if we have 64k available for himem | ||
| 412 | ; | ||
| 413 | cmp ax,64 ; Q:do we have 64k? | ||
| 414 | jb no_himem_alloc ; N: we reserve nothing for himem | ||
| 415 | ; Y: we should reserve 64k for himem | ||
| 416 | ; | ||
| 417 | ; reserve 64k for himem | ||
| 418 | ; | ||
| 419 | mov cx,64 | ||
| 420 | sub ax,cx | ||
| 421 | ; | ||
| 422 | no_himem_alloc: | ||
| 423 | ; | ||
| 424 | cmp ax,bx ; compare amount available to size needed | ||
| 425 | jae enough_mem ; Y: fine | ||
| 426 | mov bx,ax ; N: adjust size reuested to size avail | ||
| 427 | enough_mem: | ||
| 428 | ; | ||
| 429 | ; add back the memory reserved for himem as this figures in the size of | ||
| 430 | ; free extended memory | ||
| 431 | ; | ||
| 432 | add ax,cx ; adjust size to include amnt res. himem | ||
| 433 | sub ax,bx ; adjust the size of extended memory | ||
| 434 | ; after allocation | ||
| 435 | mov [total_mem],ax ; store size of extended mem available | ||
| 436 | ; | ||
| 437 | add [avail_mem],bx ; add memory available to memory pool | ||
| 438 | mov [ext_size],bx ; and indicate size allocated | ||
| 439 | ; | ||
| 440 | ; find the start address of extended memory allocated | ||
| 441 | ; | ||
| 442 | mov cx,1024 ; kb multiplier | ||
| 443 | mul cx ; dx:ax = ax*cx | ||
| 444 | add [xbase_addr_l],ax ; adjsut starting address of allocated mem | ||
| 445 | adc [xbase_addr_h],dl ; higher byte of 24 bit address | ||
| 446 | ; | ||
| 447 | x_buf_2: | ||
| 448 | ; | ||
| 449 | mov ax,[avail_mem] ; ax == Available memory | ||
| 450 | cmp ax,[pool_size] ; Q: Extended memory available? | ||
| 451 | jnb x_buf_exit ; Y: Go to finish | ||
| 452 | ; | ||
| 453 | not_enough: | ||
| 454 | or ax,ax ; Q: Any extended memory available? | ||
| 455 | jz x_buf_no_install ; N: Set error flag and exit | ||
| 456 | mov [pool_size],ax ; Y: Set pool_size to remaining memory | ||
| 457 | or [msg_flag],SIZE_ADJ_MSG ; Set buffer adjusted message bit | ||
| 458 | jmp short x_buf_exit ; And jump to exit | ||
| 459 | ; | ||
| 460 | x_buf_no_install: | ||
| 461 | or [msg_flag],MEM_ERR_MSG ; memory error found in x_bufchk | ||
| 462 | ; | ||
| 463 | x_buf_exit: | ||
| 464 | pop di | ||
| 465 | pop dx | ||
| 466 | pop cx | ||
| 467 | pop bx | ||
| 468 | pop ax | ||
| 469 | ret ; *** return *** | ||
| 470 | ; | ||
| 471 | xbuf_chk endp | ||
| 472 | ; | ||
| 473 | page | ||
| 474 | ;****************************************************************************** | ||
| 475 | ; | ||
| 476 | ; ExtAlloc - allocate extended memory - update break address for ext. mem. | ||
| 477 | ; | ||
| 478 | ; entry: DS pts to DGROUP | ||
| 479 | ; | ||
| 480 | ; exit: extended memory size | ||
| 481 | ; | ||
| 482 | ; used: none. int15 size reported by int 15 handler in MEMM adjusted. | ||
| 483 | ; | ||
| 484 | ; stack: | ||
| 485 | ; | ||
| 486 | ; modified: ISP 07/26/88 Substancially simplified. For int15 scheme | ||
| 487 | ; allocation is by lowering the size of int15 | ||
| 488 | ; reported extended memory size. | ||
| 489 | ; | ||
| 490 | ;****************************************************************************** | ||
| 491 | ExtAlloc proc near | ||
| 492 | ; | ||
| 493 | mov bx,[total_mem] ;size left after allocation to MEMM | ||
| 494 | call set_ext ; set this size in the int15 handler | ||
| 495 | ret | ||
| 496 | ; | ||
| 497 | ExtAlloc endp | ||
| 498 | ; | ||
| 499 | ;****************************************************************************** | ||
| 500 | ; | ||
| 501 | ; SysAlloc - allocate extended memory - update break address for ext. mem. | ||
| 502 | ; | ||
| 503 | ; entry: DS pts to DGROUP | ||
| 504 | ; | ||
| 505 | ; exit: system memory size | ||
| 506 | ; | ||
| 507 | ; used: none. | ||
| 508 | ; | ||
| 509 | ; stack: | ||
| 510 | ; | ||
| 511 | ; written: ISP 07/28/88 This allocates the system memory from 0000H | ||
| 512 | ; to A000h to the EMM pool. This is for the LIM | ||
| 513 | ; 4.0 implementation. | ||
| 514 | ; | ||
| 515 | ;****************************************************************************** | ||
| 516 | |||
| 517 | SysAlloc proc near | ||
| 518 | ; | ||
| 519 | push ax | ||
| 520 | push bx | ||
| 521 | push cx | ||
| 522 | ; | ||
| 523 | ; find end of memory reported by bios int 12 and round this to upper 16k. | ||
| 524 | ; | ||
| 525 | int 12h | ||
| 526 | add ax,0000fh ; | ||
| 527 | and ax,0fff0h ; round it 16k figure | ||
| 528 | ; | ||
| 529 | ; convert this to the a page # | ||
| 530 | ; | ||
| 531 | shr ax, 4 ; number of 16k pages | ||
| 532 | ; | ||
| 533 | ; start search for pages which can be reclaimed from the system mem. region | ||
| 534 | ; | ||
| 535 | mov cx,ax ; number of pages from pg0 to be examined | ||
| 536 | mov [sys_size],0 ; initialise the system memory allocate | ||
| 537 | xor bx,bx ; page # | ||
| 538 | |||
| 539 | jcxz find_sys_done | ||
| 540 | find_sys_page: | ||
| 541 | cmp cs:mappable_segs[bx], PAGE_MAPPABLE | ||
| 542 | jne find_next_sys | ||
| 543 | add [sys_size],16 ; page found add 16k to system mem size | ||
| 544 | find_next_sys: | ||
| 545 | inc bx | ||
| 546 | loop find_sys_page | ||
| 547 | find_sys_done: | ||
| 548 | |||
| 549 | mov ax,[sys_size] ; find the total memory found | ||
| 550 | add [pool_size],ax ; add this to the pool size | ||
| 551 | |||
| 552 | ; | ||
| 553 | pop cx | ||
| 554 | pop bx | ||
| 555 | pop ax | ||
| 556 | ret | ||
| 557 | |||
| 558 | SysAlloc endp | ||
| 559 | |||
| 560 | |||
| 561 | |||
| 562 | LAST ends ; End of segment | ||
| 563 | ; | ||
| 564 | end ; End of module | ||
| 565 | |||
| 566 | |||
| 567 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/ASCII_SM.EQU b/v4.0/src/MEMM/MEMM/ASCII_SM.EQU new file mode 100644 index 0000000..c4f656b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ASCII_SM.EQU | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ASCII_SM.EQU - ASCII (1968) control characters (small version) | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | NUL equ 0 ; 00 ^@ Null | ||
| 31 | BEL equ 7 ; 07 ^G Bell | ||
| 32 | BS equ 8 ; 08 ^H Backspace | ||
| 33 | TAB equ 9 ; 09 ^I (Horizontal) Tab | ||
| 34 | LF equ 10 ; 0A ^J Line Feed | ||
| 35 | FF equ 12 ; 0C ^L Form Feed | ||
| 36 | CR equ 13 ; 0D ^M Carriage Return | ||
| 37 | ASCII_ESC equ 27 ; 1B ^[ Escape | ||
| 38 | SPACE equ 32 ; 20 Space | ||
| 39 | DEL equ 127 ; 7F Delete/Rubout | ||
| 40 | |||
| 41 | .list ; end of ASCII_SM.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/DESC.INC b/v4.0/src/MEMM/MEMM/DESC.INC new file mode 100644 index 0000000..229fccb --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DESC.INC | |||
| @@ -0,0 +1,277 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: DESC.INC - Descriptor Table Definitions for 286/386 | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 04/07/86 A added bit map base to 386 TSS | ||
| 25 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 26 | ; 06/25/86 0.02 removed A0 macros | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ifndef INC_LIST | ||
| 31 | .xlist | ||
| 32 | endif | ||
| 33 | |||
| 34 | ; --------------------------------------------------- | ||
| 35 | ; | ||
| 36 | ; Definitions for the access byte in a descriptor | ||
| 37 | ; | ||
| 38 | ; --------------------------------------------------- | ||
| 39 | |||
| 40 | |||
| 41 | ; Following fields are common to segment and control descriptors | ||
| 42 | |||
| 43 | D_PRES equ 080h ; present in memory | ||
| 44 | D_NOTPRES equ 0 ; not present in memory | ||
| 45 | |||
| 46 | D_DPL0 equ 0 ; Ring 0 | ||
| 47 | D_DPL1 equ 020h ; Ring 1 | ||
| 48 | D_DPL2 equ 040h ; Ring 2 | ||
| 49 | D_DPL3 equ 060h ; Ring 3 | ||
| 50 | |||
| 51 | D_SEG equ 010h ; Segment descriptor | ||
| 52 | D_CTRL equ 0 ; Control descriptor | ||
| 53 | |||
| 54 | |||
| 55 | ; Following fields are specific to control descriptors | ||
| 56 | |||
| 57 | D_TSS equ 01h ; A Free TSS | ||
| 58 | D_LDT equ 02h ; LDT | ||
| 59 | D_TSS_BUSY equ 03h ; A Busy TSS | ||
| 60 | D_CALLGATE equ 04h ; call gate | ||
| 61 | D_TASKGATE equ 05h ; task gate | ||
| 62 | D_INTGATE equ 06h ; interrupt gate | ||
| 63 | D_TRAPGATE equ 07h ; trap gate | ||
| 64 | ; 8 is invalid | ||
| 65 | D_386TSS equ 9 ; available 386 TSS | ||
| 66 | ; 0ah - Intel Reserved | ||
| 67 | D_BUSY386TSS equ 0bh ; busy 386 TSS | ||
| 68 | D_386CALL_GATE equ 0ch ; 386 call gate | ||
| 69 | ; 0dh - Intel Reserved | ||
| 70 | D_386INT_GATE equ 0eh ; 386 interrupt gate | ||
| 71 | D_386TRAP_GATE equ 0fh ; 386 trap gate | ||
| 72 | |||
| 73 | ; Following fields are specific to segment descriptors | ||
| 74 | |||
| 75 | D_CODE equ 08h ; code | ||
| 76 | D_DATA equ 0 ; data | ||
| 77 | |||
| 78 | D_CONFORM equ 04h ; if code, conforming | ||
| 79 | D_EXPDN equ 04h ; if data, expand down | ||
| 80 | |||
| 81 | D_RX equ 02h ; if code, readable | ||
| 82 | D_X equ 0 ; if code, exec only | ||
| 83 | D_W equ 02h ; if data, writable | ||
| 84 | D_R equ 0 ; if data, read only | ||
| 85 | |||
| 86 | D_ACCESSED equ 1 ; segment accessed bit | ||
| 87 | |||
| 88 | |||
| 89 | ; Useful combination access rights bytes | ||
| 90 | |||
| 91 | D_DATA0 equ (D_PRES+D_DPL0+D_SEG+D_DATA+D_W) ; Ring 0 rw data | ||
| 92 | D_CODE0 equ (D_PRES+D_DPL0+D_SEG+D_CODE+D_RX) ; Ring 0 rx code | ||
| 93 | D_TRAP0 equ (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE) ; Ring 0 trap gate | ||
| 94 | D_INT0 equ (D_PRES+D_DPL0+D_CTRL+D_INTGATE) ; Ring 0 int gate | ||
| 95 | D_TSS0 equ (D_PRES+D_DPL0+D_CTRL+D_TSS) ; Ring 0 TSS | ||
| 96 | D_386TSS0 equ (D_PRES+D_DPL0+D_CTRL+D_386TSS) ; Ring 0 TSS | ||
| 97 | D_LDT0 equ (D_PRES+D_DPL0+D_CTRL+D_LDT) ; Ring 0 LDT | ||
| 98 | D_386INT0 equ (D_PRES+D_DPL0+D_CTRL+D_386INT_GATE) ; Ring 0 int gate | ||
| 99 | |||
| 100 | ;D_DATA1 equ (D_PRES+D_DPL1+D_SEG+D_DATA+D_W) ; Ring 1 rw data | ||
| 101 | ;D_CODE1 equ (D_PRES+D_DPL1+D_SEG+D_CODE+D_RX) ; Ring 1 rx code | ||
| 102 | |||
| 103 | ;D_DATA2 equ (D_PRES+D_DPL2+D_SEG+D_DATA+D_W) ; Ring 2 rw data | ||
| 104 | ;D_CODE2 equ (D_PRES+D_DPL2+D_SEG+D_CODE+D_RX) ; Ring 2 rx code | ||
| 105 | |||
| 106 | D_DATA3 equ (D_PRES+D_DPL3+D_SEG+D_DATA+D_W) ; Ring 3 rw data | ||
| 107 | D_CODE3 equ (D_PRES+D_DPL3+D_SEG+D_CODE+D_RX) ; Ring 3 rx code | ||
| 108 | D_INT3 equ (D_PRES+D_DPL3+D_CTRL+D_INTGATE) ; Ring 3 int gate | ||
| 109 | D_GATE3 equ (D_PRES+D_DPL3+D_CTRL+D_CALLGATE) ; Ring 3 call gate | ||
| 110 | D_386INT3 equ (D_PRES+D_DPL3+D_CTRL+D_386INT_GATE) ; Ring 3 int gate | ||
| 111 | |||
| 112 | ; 386 Extensions | ||
| 113 | |||
| 114 | D_B_BIT equ (1 SHL 6) ; 32 bit stack offsets | ||
| 115 | |||
| 116 | |||
| 117 | ; Masks for selector fields | ||
| 118 | |||
| 119 | SELECTOR_MASK equ 0fff8h ; selector index | ||
| 120 | SEL_LOW_MASK equ 0f8h ; mask for low byte of sel indx | ||
| 121 | TABLE_MASK equ 04h ; table bit | ||
| 122 | RPL_MASK equ 03h ; privilige bits | ||
| 123 | RPL_CLR equ not 03h ; clear ring bits | ||
| 124 | |||
| 125 | |||
| 126 | ; Machine Status Word bits | ||
| 127 | |||
| 128 | MSW_PROTECT equ 1 ; virtual mode bit | ||
| 129 | |||
| 130 | |||
| 131 | ; System IOPL | ||
| 132 | |||
| 133 | SYS_IOPL equ 3000h ; wide open | ||
| 134 | CLEAR_IOPL equ 0cfffh ; mask to remove IOPL bits | ||
| 135 | |||
| 136 | |||
| 137 | ; Kernel Stack Size (TO BE ADDED) | ||
| 138 | |||
| 139 | STK_SIZE equ 4000h ; TO BE ADDED | ||
| 140 | |||
| 141 | |||
| 142 | ; -------------------------------------------------- | ||
| 143 | ; | ||
| 144 | ; Macros for creating descriptor table entries | ||
| 145 | ; | ||
| 146 | ; -------------------------------------------------- | ||
| 147 | |||
| 148 | |||
| 149 | |||
| 150 | ; structure for 386 descriptor | ||
| 151 | |||
| 152 | desc struc | ||
| 153 | LIMIT dw 0 ; offset of last byte in segment | ||
| 154 | BASE_LOW dw 0 ; Low 16 bits of 24 bit base address | ||
| 155 | BASE_HIGH db 0 ; High 8 bits of 24 bit base address | ||
| 156 | RIGHTS db 0 ; access rights | ||
| 157 | RES386 db 0 ; reserved for 386 | ||
| 158 | BASE_XHI db 0 ; High 8 bits of 32 bit base address | ||
| 159 | desc ends | ||
| 160 | |||
| 161 | ; MASK for RES386 | ||
| 162 | |||
| 163 | R_GRAN equ 10000000b ; granularity bit | ||
| 164 | R_AVL equ 00010000b ; available | ||
| 165 | R_LIMIT_XHI equ 00001111b ; limit bits 16..19 | ||
| 166 | |||
| 167 | ; IDT_ENTRY - for interrupt and task gate definitions in IDT | ||
| 168 | |||
| 169 | IDT_ENTRY macro sel, off, acc | ||
| 170 | dw off ; offset | ||
| 171 | dw sel ; selector | ||
| 172 | db 0 ; word count, unused for trap/int gates | ||
| 173 | db acc ; access rights byte | ||
| 174 | dw 0 ; reserved, must be 0 for 386 | ||
| 175 | endm | ||
| 176 | |||
| 177 | |||
| 178 | ; GDT_ENTRY - for static initialisation of GDT entries | ||
| 179 | |||
| 180 | GDT_ENTRY macro BaseLow, BaseHi, Size, Access | ||
| 181 | dw Size - 1 ; segment limit | ||
| 182 | dw BaseLow ; low word of 24 bit base address | ||
| 183 | db BaseHi ; high byte of base address | ||
| 184 | db Access ; access rights byte | ||
| 185 | dw 0 ; reserved, must be 0 for 386 | ||
| 186 | endm | ||
| 187 | |||
| 188 | |||
| 189 | ; LDT_ENTRY - for static initialisation of LDT entries | ||
| 190 | |||
| 191 | LDT_ENTRY macro BaseLow, BaseHi, Size, Access | ||
| 192 | dw Size - 1 ; segment limit | ||
| 193 | dw BaseLow ; low word of 24 bit base address | ||
| 194 | db BaseHi ; high byte of base address | ||
| 195 | db Access ; access rights byte | ||
| 196 | dw 0 ; reserved, must be 0 for 386 | ||
| 197 | endm | ||
| 198 | |||
| 199 | |||
| 200 | ;*** 286 TSS Format | ||
| 201 | ; | ||
| 202 | |||
| 203 | TSS286STRUC struc | ||
| 204 | |||
| 205 | TSS286_BackLink dw 0 ; back link selector to TSS | ||
| 206 | TSS286_SP0 dw 0 ; ring 0 sp | ||
| 207 | TSS286_SS0 dw 0 ; ring 0 ss | ||
| 208 | TSS286_SP1 dw 0 ; ring 1 sp | ||
| 209 | TSS286_SS1 dw 0 ; ring 1 ss | ||
| 210 | TSS286_SP2 dw 0 ; ring 2 sp | ||
| 211 | TSS286_SS2 dw 0 ; ring 2 ss | ||
| 212 | TSS286_IP dw 0 ; entry point IP | ||
| 213 | TSS286_Flags dw 0 ; flag word | ||
| 214 | TSS286_AX dw 0 ; AX | ||
| 215 | TSS286_CX dw 0 ; CX | ||
| 216 | TSS286_DX dw 0 ; DX | ||
| 217 | TSS286_BX dw 0 ; BX | ||
| 218 | TSS286_SP dw 0 ; SP | ||
| 219 | TSS286_BP dw 0 ; BP | ||
| 220 | TSS286_SI dw 0 ; SI | ||
| 221 | TSS286_DI dw 0 ; DI | ||
| 222 | TSS286_ES dw 0 ; ES | ||
| 223 | TSS286_CS dw 0 ; CS | ||
| 224 | TSS286_SS dw 0 ; SS | ||
| 225 | TSS286_DS dw 0 ; DS | ||
| 226 | TSS286_LDT dw 0 ; LDT | ||
| 227 | |||
| 228 | TSS286STRUC ends | ||
| 229 | |||
| 230 | ;*** 386 TSS Format | ||
| 231 | ; | ||
| 232 | |||
| 233 | TSS386STRUC struc | ||
| 234 | |||
| 235 | TSS386_BackLink dw 0 ; back link selector to TSS | ||
| 236 | TSS386_Unused1 dw 0 ; unused | ||
| 237 | TSS386_ESP0lo dw 0 ; ring 0 ESP low word | ||
| 238 | TSS386_ESP0hi dw 0 ; ring 0 ESP high word | ||
| 239 | TSS386_SS0 dw 0 ; ring 0 SS | ||
| 240 | TSS386_Unused2 dw 0 ; unused | ||
| 241 | TSS386_ESP1 dd 0 ; ring 1 ESP | ||
| 242 | TSS386_SS1 dw 0 ; ring 1 SS | ||
| 243 | TSS386_Unused3 dw 0 ; unused | ||
| 244 | TSS386_ESP2 dd 0 ; ring 2 ESP | ||
| 245 | TSS386_SS2 dw 0 ; ring 2 SS | ||
| 246 | TSS386_Unused4 dw 0 ; unused | ||
| 247 | TSS386_CR3 dd 0 ; CR3 | ||
| 248 | TSS386_EIP dd 0 ; EIP | ||
| 249 | TSS386_EFLAGS dd 0 ; EFLAGS | ||
| 250 | TSS386_EAX dd 0 ; EAX | ||
| 251 | TSS386_ECX dd 0 ; ECX | ||
| 252 | TSS386_EDX dd 0 ; EDX | ||
| 253 | TSS386_EBX dd 0 ; EBX | ||
| 254 | TSS386_ESP dd 0 ; ESP | ||
| 255 | TSS386_EBP dd 0 ; EBP | ||
| 256 | TSS386_ESI dd 0 ; ESI | ||
| 257 | TSS386_EDI dd 0 ; EDI | ||
| 258 | TSS386_ES dw 0 ; ES | ||
| 259 | TSS386_Unused5 dw 0 ; Unused | ||
| 260 | TSS386_CS dw 0 ; CS | ||
| 261 | TSS386_Unused6 dw 0 ; Unused | ||
| 262 | TSS386_SS dw 0 ; SS | ||
| 263 | TSS386_Unused7 dw 0 ; Unused | ||
| 264 | TSS386_DS dw 0 ; DS | ||
| 265 | TSS386_Unused8 dw 0 ; Unused | ||
| 266 | TSS386_FS dw 0 ; FS | ||
| 267 | TSS386_Unused9 dw 0 ; Unused | ||
| 268 | TSS386_GS dw 0 ; GS | ||
| 269 | TSS386_Unused10 dw 0 ; Unused | ||
| 270 | TSS386_LDT dw 0 ; LDT | ||
| 271 | TSS386_Unused11 dw 0 ; Unused | ||
| 272 | TaskAttributes dw 0 ; Task Attributes | ||
| 273 | BitMapBase dw 0 ; offset of Base of Bit Map | ||
| 274 | TSS386STRUC ends | ||
| 275 | |||
| 276 | .list ; end of DESC.INC | ||
| 277 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/DISP.INC b/v4.0/src/MEMM/MEMM/DISP.INC new file mode 100644 index 0000000..96eeb7b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DISP.INC | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | extrn PrintString:near | ||
| 2 | extrn PrintHex:near | ||
| 3 | |||
| 4 | display macro string | ||
| 5 | local dbs,disp_exit | ||
| 6 | pushf | ||
| 7 | push ds | ||
| 8 | push es | ||
| 9 | |||
| 10 | push cs | ||
| 11 | pop ds | ||
| 12 | push cs | ||
| 13 | pop es | ||
| 14 | |||
| 15 | push si | ||
| 16 | mov si,offset cs:dbs | ||
| 17 | call PrintString | ||
| 18 | pop si | ||
| 19 | pop es | ||
| 20 | pop ds | ||
| 21 | popf | ||
| 22 | jmp disp_exit | ||
| 23 | |||
| 24 | dbs db &string,0 | ||
| 25 | |||
| 26 | disp_exit: | ||
| 27 | endm | ||
| 28 | |||
| 29 | content macro reg | ||
| 30 | pushf | ||
| 31 | push ds | ||
| 32 | push es | ||
| 33 | push ax | ||
| 34 | |||
| 35 | mov ax,reg | ||
| 36 | |||
| 37 | push cs | ||
| 38 | pop ds | ||
| 39 | push cs | ||
| 40 | pop es | ||
| 41 | |||
| 42 | call PrintHex | ||
| 43 | |||
| 44 | pop ax | ||
| 45 | pop es | ||
| 46 | pop ds | ||
| 47 | popf | ||
| 48 | endm | ||
| 49 | |||
| 50 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/DMA.INC b/v4.0/src/MEMM/MEMM/DMA.INC new file mode 100644 index 0000000..06bed73 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DMA.INC | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ELIM.INC - include for LIM I/O traps (DMA ports) | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: April 9, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 04/09/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; 07/01/86 0.03 DMA trapping related equates added | ||
| 26 | ; | ||
| 27 | ; DATE AUTHOR DESCRIPTION | ||
| 28 | ; ------- -------- ------------------------------------------------------- | ||
| 29 | ; 06/21/88 ISP Removed the Intel Above Board Port Definitions | ||
| 30 | ; 07/27/88 JHB Added Channel 4 ports, ports for Mode Regs and changed | ||
| 31 | ; DMARegRec and DMARegBuf structure definitions - lifted | ||
| 32 | ; from vdmad.inc in Win386/2.03. | ||
| 33 | ; - Jaywant H Bharadwaj | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ifndef INC_LIST | ||
| 37 | .xlist | ||
| 38 | endif | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ; DMA related ports | ||
| 42 | ; | ||
| 43 | DMA_P0 equ 0087h ; DMA page register for Channel 0 | ||
| 44 | DMA_P1 equ 0083h ; DMA page register for Channel 1 | ||
| 45 | DMA_P2 equ 0081h ; DMA page register for Channel 2 | ||
| 46 | DMA_P3 equ 0082h ; DMA page register for Channel 3 | ||
| 47 | DMA_P5 equ 008Bh ; DMA page register for Channel 5 | ||
| 48 | DMA_P6 equ 0089h ; DMA page register for Channel 6 | ||
| 49 | DMA_P7 equ 008Ah ; DMA page register for Channel 7 | ||
| 50 | DMA_P4 equ 0080h ; dummy page reg for channel 4 | ||
| 51 | |||
| 52 | DMA_B0 equ 0000h ; DMA base register for Channel 0 | ||
| 53 | DMA_C0 equ 0001h ; DMA count register for Channel 0 | ||
| 54 | DMA_B1 equ 0002h ; DMA base register for Channel 1 | ||
| 55 | DMA_C1 equ 0003h ; DMA count register for Channel 1 | ||
| 56 | DMA_B2 equ 0004h ; DMA base register for Channel 2 | ||
| 57 | DMA_C2 equ 0005h ; DMA count register for Channel 2 | ||
| 58 | DMA_B3 equ 0006h ; DMA base register for Channel 3 | ||
| 59 | DMA_C3 equ 0007h ; DMA count register for Channel 3 | ||
| 60 | DMA_B4 equ 00C0h ; DMA base register for Channel 4 | ||
| 61 | DMA_C4 equ 00C2h ; DMA count register for Channel 4 | ||
| 62 | DMA_B5 equ 00C4h ; DMA base register for Channel 5 | ||
| 63 | DMA_C5 equ 00C6h ; DMA count register for Channel 5 | ||
| 64 | DMA_B6 equ 00C8h ; DMA base register for Channel 6 | ||
| 65 | DMA_C6 equ 00CAh ; DMA count register for Channel 6 | ||
| 66 | DMA_B7 equ 00CCh ; DMA base register for Channel 7 | ||
| 67 | DMA_C7 equ 00CEh ; DMA count register for Channel 7 | ||
| 68 | |||
| 69 | DMA1_CLR_FF equ 000Ch ; clear flip-flop cmd for channels 0-3 | ||
| 70 | DMA2_CLR_FF equ 00D8h ; clear flip-flop cmd for channels 5-7 | ||
| 71 | |||
| 72 | |||
| 73 | DMA1_MODE equ 000Bh ; Mode register for channels 0-3 | ||
| 74 | DMA2_MODE equ 00D6h ; Mode register for channels 4-7 | ||
| 75 | |||
| 76 | DMA_M_CHANNEL equ 03h ; Mask for channel | ||
| 77 | DMA_M_OPERATION equ 0Ch ; Mask for operation | ||
| 78 | DMA_M_16BIT equ 040h ; 16bit transfers (PS/2 ext mode) | ||
| 79 | |||
| 80 | DMA_M_VERIFY equ 0 ; Verify operation | ||
| 81 | DMA_M_WRITE equ 4 ; Write | ||
| 82 | |||
| 83 | |||
| 84 | ;************************************************************************** | ||
| 85 | ; New defintions for DMARegRec and DMARegBuf - 7/27/88 | ||
| 86 | ; | ||
| 87 | ; | ||
| 88 | ; DMA Register Save Structure | ||
| 89 | ; | ||
| 90 | |||
| 91 | ; | ||
| 92 | ; note: the DMA code in ELIMTRAP.ASM is tuned to this structure's size = 16 | ||
| 93 | ; if you change the size, you had better change the code ! | ||
| 94 | ; LinAdr and PhysAdr have to be dwords | ||
| 95 | ; count though 16 bits long is left as a dword since the rest of the ported | ||
| 96 | ; 386 code is dependent on this structure being 16 bytes long. | ||
| 97 | ; | ||
| 98 | |||
| 99 | DMARegRec struc | ||
| 100 | DMALinAdr dd 00000000 ; Channel Linear Base Register | ||
| 101 | DMAPhyAdr dd 00000000 ; Channel Physical Base Register | ||
| 102 | DMACount dd 00000000 ; Channel Count Register | ||
| 103 | DMAPagePort db ? ; byte addr of page reg | ||
| 104 | DMABasePort db ? ; byte addr of base addr reg | ||
| 105 | DMACntPort db ? ; byte addr of cnt addr reg | ||
| 106 | DMAMode db ? ; Mode register | ||
| 107 | DMARegRec ends | ||
| 108 | |||
| 109 | DMARegBuf struc | ||
| 110 | Chnl0 db (size DMARegRec - 4) dup (00), DMA_P0, DMA_B0, DMA_C0, 0 | ||
| 111 | Chnl1 db (size DMARegRec - 4) dup (00), DMA_P1, DMA_B1, DMA_C1, 0 | ||
| 112 | Chnl2 db (size DMARegRec - 4) dup (00), DMA_P2, DMA_B2, DMA_C2, 0 | ||
| 113 | Chnl3 db (size DMARegRec - 4) dup (00), DMA_P3, DMA_B3, DMA_C3, 0 | ||
| 114 | Chnl4 db (size DMARegRec - 4) dup (00), DMA_P4, DMA_B4, DMA_C4, DMA_M_16BIT | ||
| 115 | Chnl5 db (size DMARegRec - 4) dup (00), DMA_P5, DMA_B5, DMA_C5, DMA_M_16BIT | ||
| 116 | Chnl6 db (size DMARegRec - 4) dup (00), DMA_P6, DMA_B6, DMA_C6, DMA_M_16BIT | ||
| 117 | Chnl7 db (size DMARegRec - 4) dup (00), DMA_P7, DMA_B7, DMA_C7, DMA_M_16BIT | ||
| 118 | DMAFF1 db 00 ; Controller 1 FlipFlop State | ||
| 119 | DMAFF2 db 00 ; Controller 2 FlipFlop State | ||
| 120 | DMA_Xfun db 0 ; Extended Operation Function | ||
| 121 | DMA_Xchn db 0 ; Extended Operation Channel | ||
| 122 | DMARegBuf ends | ||
| 123 | |||
| 124 | DMAREG_CTRL2_INDEX equ 4 * 2 ; 2 * 1st channel # on 2nd cntlr | ||
| 125 | |||
| 126 | |||
| 127 | ;************************************************************************** | ||
| 128 | ; | ||
| 129 | ; Macros taken from PS2.INC in Win/386 2.03 | ||
| 130 | ; | ||
| 131 | ;-------------------------------------------------------------------------- | ||
| 132 | |||
| 133 | ; STANDARD ROM BIOS MACHINE TYPES used in ROM_BIOS_Machine_ID | ||
| 134 | |||
| 135 | RBMI_PC equ 0FFh | ||
| 136 | RBMI_PCXT equ 0FEh | ||
| 137 | RBMI_PCjr equ 0FDh | ||
| 138 | RBMI_PCAT equ 0FCh | ||
| 139 | RBMI_PCConvertible equ 0F9h | ||
| 140 | RBMI_Sys80 equ 0F8h | ||
| 141 | RBMI_CompaqPortable equ 000h | ||
| 142 | |||
| 143 | ;****************************************************************************** | ||
| 144 | ; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address | ||
| 145 | ; | ||
| 146 | ; ENTRY: 386 PROTECTED MODE | ||
| 147 | ; DS -> 0 | ||
| 148 | ; ES -> 0 | ||
| 149 | ; EAX - Word Address | ||
| 150 | ; | ||
| 151 | ; EXIT: EAX - Byte address | ||
| 152 | ; | ||
| 153 | ; USED: | ||
| 154 | ;------------------------------------------------------------------------------ | ||
| 155 | DMA_WADDR_TO_BADDR MACRO | ||
| 156 | LOCAL Not_AT | ||
| 157 | extrn ROM_BIOS_Machine_ID:byte | ||
| 158 | |||
| 159 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 160 | jbe short Not_AT ; If running on EBIOS machine | ||
| 161 | |||
| 162 | ror eax,16 ; AX = high word | ||
| 163 | shr al,1 ; adjust for D0 null in page reg | ||
| 164 | rol eax,17 ; EAX = address w/ adjust for | ||
| 165 | ; 'A0' offset | ||
| 166 | Not_At: | ||
| 167 | shl ecx, 1 ; Adjust for word units | ||
| 168 | ENDM | ||
| 169 | |||
| 170 | |||
| 171 | ;****************************************************************************** | ||
| 172 | ; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address | ||
| 173 | ; | ||
| 174 | ; ENTRY: 386 PROTECTED MODE | ||
| 175 | ; DS -> 0 | ||
| 176 | ; ES -> 0 | ||
| 177 | ; EAX - Word Address | ||
| 178 | ; | ||
| 179 | ; EXIT: EAX - Byte address | ||
| 180 | ; | ||
| 181 | ; USED: | ||
| 182 | ;------------------------------------------------------------------------------ | ||
| 183 | DMA_BADDR_TO_WADDR MACRO | ||
| 184 | LOCAL Not_AT | ||
| 185 | extrn ROM_BIOS_Machine_ID:byte | ||
| 186 | |||
| 187 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 188 | jbe short Not_AT ; If running on EBIOS machine | ||
| 189 | |||
| 190 | shr eax, 1 ; Adjust for implied 'A0' | ||
| 191 | push ax ; Save A16-A1 | ||
| 192 | xor ax, ax | ||
| 193 | shl eax, 1 ; Adjust for unused Pg Reg D0 | ||
| 194 | pop ax ; Restore A16-A1 | ||
| 195 | Not_At: | ||
| 196 | ENDM | ||
| 197 | |||
| 198 | |||
| 199 | |||
| 200 | ;**************************************************************************** | ||
| 201 | ; Old definitions for memm LIM 3.2 - not used anymore - 7/27/88 | ||
| 202 | ; | ||
| 203 | ; DMA Register Save Structure | ||
| 204 | ; | ||
| 205 | ;Chnl1Idx equ 0 ; Address offset in Address tables | ||
| 206 | ;Chnl2Idx equ 2 ; Address offset in Address tables | ||
| 207 | ;Chnl3Idx equ 4 ; Address offset in Address tables | ||
| 208 | ;Chnl5Idx equ 6 ; Address offset in Address tables | ||
| 209 | ;Chnl6Idx equ 8 ; Address offset in Address tables | ||
| 210 | ;Chnl7Idx equ 10 ; Address offset in Address tables | ||
| 211 | ; | ||
| 212 | ;DMARegRec struc | ||
| 213 | ;DMALinAdr dd 00000000 ; Channel Linear Base Register | ||
| 214 | ;DMAPhyAdr dd 00000000 ; Channel Physical Base Register | ||
| 215 | ;DMACount dd 00000000 ; Channel Count Register | ||
| 216 | ;DMAChnlIdx db ? ; Channel identifier index | ||
| 217 | ;DMARegRec ends | ||
| 218 | ; | ||
| 219 | ;DMARegBuf struc | ||
| 220 | ;Chnl1 db (size DMARegRec - 1) dup (00), Chnl1Idx | ||
| 221 | ;Chnl2 db (size DMARegRec - 1) dup (00), Chnl2Idx | ||
| 222 | ;Chnl3 db (size DMARegRec - 1) dup (00), Chnl3Idx | ||
| 223 | ;Chnl5 db (size DMARegRec - 1) dup (00), Chnl5Idx | ||
| 224 | ;Chnl6 db (size DMARegRec - 1) dup (00), Chnl6Idx | ||
| 225 | ;Chnl7 db (size DMARegRec - 1) dup (00), Chnl7Idx | ||
| 226 | ;DMAFF1 db 00 ; Controller 1 FlipFlop State | ||
| 227 | ;DMAFF2 db 00 ; Controller 2 FlipFlop State | ||
| 228 | ;DMARegBuf ends | ||
| 229 | ; | ||
| 230 | ;****************************************************************************** | ||
| 231 | |||
| 232 | |||
| 233 | .list ; end of ELIM.INC | ||
| 234 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/DRIVER.EQU b/v4.0/src/MEMM/MEMM/DRIVER.EQU new file mode 100644 index 0000000..8e12e90 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DRIVER.EQU | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: DRIVER.EQU - MS-DOS device driver equates | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | ; | ||
| 31 | ; Device driver attribute equates | ||
| 32 | ; | ||
| 33 | CHAR_DEV EQU 8000H | ||
| 34 | IOCTL_SUP EQU 4000H | ||
| 35 | NON_IBM EQU 2000H | ||
| 36 | CLK_DEV EQU 0008H | ||
| 37 | NUL_DEV EQU 0004H | ||
| 38 | OUT_DEV EQU 0002H | ||
| 39 | INP_DEV EQU 0001H | ||
| 40 | ; | ||
| 41 | ; Device driver command code equates | ||
| 42 | ; | ||
| 43 | INIT EQU 0 | ||
| 44 | MEDIA EQU 1 | ||
| 45 | BUILD_BPB EQU 2 | ||
| 46 | IOCTL_INP EQU 3 | ||
| 47 | INPUT_READ EQU 4 | ||
| 48 | NON_INPUT EQU 5 | ||
| 49 | INP_STATUS EQU 6 | ||
| 50 | INP_FLUSH EQU 7 | ||
| 51 | OUTPUT_WRITE EQU 8 | ||
| 52 | OUTPUT_VER EQU 9 | ||
| 53 | OUT_STATUS EQU 10 | ||
| 54 | OUT_FLUSH EQU 11 | ||
| 55 | IOCTL_OUT EQU 12 | ||
| 56 | ; | ||
| 57 | ; Device driver status word equates | ||
| 58 | ; | ||
| 59 | ERROR EQU 8000H | ||
| 60 | BUSY EQU 0200H | ||
| 61 | DONE EQU 0100H | ||
| 62 | ERR EQU 80H | ||
| 63 | BUS EQU 02H | ||
| 64 | DON EQU 01H | ||
| 65 | ; | ||
| 66 | ; Device driver i/o control status word equates | ||
| 67 | ; | ||
| 68 | ISDEV EQU 0080H | ||
| 69 | EOF EQU 0040H | ||
| 70 | RAW EQU 0020H | ||
| 71 | ISCLK EQU 0008H | ||
| 72 | ISNUL EQU 0004H | ||
| 73 | ISCOT EQU 0002H | ||
| 74 | ISCIN EQU 0001H | ||
| 75 | ; | ||
| 76 | ; Device driver error code equates | ||
| 77 | ; | ||
| 78 | WRT_PROT_VIO EQU 00H | ||
| 79 | UNK_UNIT EQU 01H | ||
| 80 | DEV_NOT_RDY EQU 02H | ||
| 81 | UNK_COMMAND EQU 03H | ||
| 82 | CRC_ERROR EQU 04H | ||
| 83 | BAD_DRIVE EQU 05H | ||
| 84 | SEEK_ERROR EQU 06H | ||
| 85 | UNK_MEDIA EQU 07H | ||
| 86 | SEC_NOT_FND EQU 08H | ||
| 87 | OUT_OF_PAPER EQU 09H | ||
| 88 | WRITE_FAULT EQU 0AH | ||
| 89 | READ_FAULT EQU 0BH | ||
| 90 | GENERAL_FAIL EQU 0CH | ||
| 91 | ; | ||
| 92 | ; Device driver function call equates | ||
| 93 | ; | ||
| 94 | NUMBER_UNITS EQU BYTE PTR 0DH | ||
| 95 | ENDING_ADDR EQU DWORD PTR 0EH | ||
| 96 | BPB_ARRAY EQU DWORD PTR 12H | ||
| 97 | DESC_BYTE EQU BYTE PTR 0DH | ||
| 98 | RETURN_INFO EQU BYTE PTR 0EH | ||
| 99 | BUFFER_ADDR EQU DWORD PTR 0EH | ||
| 100 | BPB_PTR EQU DWORD PTR 12H | ||
| 101 | TRANS_COUNT EQU WORD PTR 12H | ||
| 102 | TRANS_ADDR EQU WORD PTR 14H | ||
| 103 | BYTE_READ EQU BYTE PTR 0DH | ||
| 104 | |||
| 105 | .list ; end of DRIVER.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/DRIVER.STR b/v4.0/src/MEMM/MEMM/DRIVER.STR new file mode 100644 index 0000000..dfb7e90 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/DRIVER.STR | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: DRIVER.STR - MS-DOS Device Driver structures | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | ; | ||
| 32 | ; Device driver header structure | ||
| 33 | ; | ||
| 34 | DEVICE_HEADER STRUC | ||
| 35 | DEV_PTR DD 0 | ||
| 36 | DEV_ATTR DW 0 | ||
| 37 | STRAT_PTR DW 0 | ||
| 38 | INT_PTR DW 0 | ||
| 39 | DEV_NAME DB " " | ||
| 40 | DEVICE_HEADER ENDS | ||
| 41 | DEV_OFF EQU WORD PTR DEV_PTR | ||
| 42 | DEV_SEG EQU WORD PTR DEV_PTR+2 | ||
| 43 | ; | ||
| 44 | ; Device driver request header structure | ||
| 45 | ; | ||
| 46 | REQUEST_HEADER STRUC | ||
| 47 | HDR_LEN DB 0 | ||
| 48 | UNIT_CODE DB 0 | ||
| 49 | COMMAND_CODE DB 0 | ||
| 50 | STATUS_WORD DW 0 | ||
| 51 | RES_AREA DB 0,0,0,0,0,0,0,0 | ||
| 52 | OP_DATA DB 0 | ||
| 53 | REQUEST_HEADER ENDS | ||
| 54 | ; | ||
| 55 | ; Initialize command request header structure | ||
| 56 | ; | ||
| 57 | INIT_HEADER STRUC | ||
| 58 | DB 13 DUP (?) | ||
| 59 | NUM_UNITS DB 0 | ||
| 60 | BRK_ADDR DD 0 | ||
| 61 | ARG_PTR DD 0 | ||
| 62 | DRV_NUM DB 0 | ||
| 63 | INIT_HEADER ENDS | ||
| 64 | BRK_OFF EQU WORD PTR BRK_ADDR | ||
| 65 | BRK_SEG EQU WORD PTR BRK_ADDR+2 | ||
| 66 | ARG_OFF EQU WORD PTR ARG_PTR | ||
| 67 | ARG_SEG EQU WORD PTR ARG_PTR+2 | ||
| 68 | ; | ||
| 69 | ; Media check request header structure | ||
| 70 | ; | ||
| 71 | MEDIA_HEADER STRUC | ||
| 72 | DB 13 DUP (?) | ||
| 73 | MEDIA_BYTE DB 0 | ||
| 74 | RET_BYTE DB 0 | ||
| 75 | VOL_PTR DD 0 | ||
| 76 | MEDIA_HEADER ENDS | ||
| 77 | VOL_OFF EQU WORD PTR VOL_PTR | ||
| 78 | VOL_SEG EQU WORD PTR VOL_PTR+2 | ||
| 79 | ; | ||
| 80 | ; Build BPB request header structure | ||
| 81 | ; | ||
| 82 | BPB_HEADER STRUC | ||
| 83 | DB 13 DUP (?) | ||
| 84 | BPB_DESC DB 0 | ||
| 85 | BPB_TRANS DD 0 | ||
| 86 | TABLE_PTR DD 0 | ||
| 87 | BPB_HEADER ENDS | ||
| 88 | BPB_OFF EQU WORD PTR BPB_TRANS | ||
| 89 | BPB_SEG EQU WORD PTR BPB_TRANS+2 | ||
| 90 | TABLE_OFF EQU WORD PTR TABLE_PTR | ||
| 91 | TABLE_SEG EQU WORD PTR TABLE_PTR+2 | ||
| 92 | ; | ||
| 93 | ; Input/output request header structure | ||
| 94 | ; | ||
| 95 | IO_HEADER STRUC | ||
| 96 | DB 13 DUP (?) | ||
| 97 | IO_DESC DB 0 | ||
| 98 | IO_TRANS DD 0 | ||
| 99 | IO_COUNT DW 0 | ||
| 100 | IO_START DW 0 | ||
| 101 | VOL_ID DD 0 | ||
| 102 | IO_HEADER ENDS | ||
| 103 | IO_OFF EQU WORD PTR IO_TRANS | ||
| 104 | IO_SEG EQU WORD PTR IO_TRANS+2 | ||
| 105 | ID_OFF EQU WORD PTR VOL_ID | ||
| 106 | ID_SEG EQU WORD PTR VOL_ID+2 | ||
| 107 | ; | ||
| 108 | ; Device driver BIOS Parameter Block (BPB) structure | ||
| 109 | ; | ||
| 110 | BPB_BLOCK STRUC | ||
| 111 | BYTES_PER_SECTOR DW 0 | ||
| 112 | SECTORS_PER_ALLOC DB 0 | ||
| 113 | RES_SECTORS DW 0 | ||
| 114 | NUM_FATS DB 0 | ||
| 115 | ROOT_DIR_ENTRIES DW 0 | ||
| 116 | NUMBER_OF_SECTORS DW 0 | ||
| 117 | MEDIA_DESC DB 0 | ||
| 118 | SECTORS_PER_FAT DW 0 | ||
| 119 | BPB_BLOCK ENDS | ||
| 120 | ; | ||
| 121 | ; Device driver BIOS Parameter option block structure | ||
| 122 | ; | ||
| 123 | BPB_OPTION STRUC | ||
| 124 | SECTORS_PER_TRACK DW 0 | ||
| 125 | NUMBER_OF_HEADS DW 0 | ||
| 126 | HIDDEN_SECTORS DW 0 | ||
| 127 | BPB_OPTION ENDS | ||
| 128 | |||
| 129 | .list ; end of DRIVER.STR | ||
diff --git a/v4.0/src/MEMM/MEMM/EKBD.ASM b/v4.0/src/MEMM/MEMM/EKBD.ASM new file mode 100644 index 0000000..9f8a8f2 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EKBD.ASM | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EKBD - get keyboard make codes | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 8 | ; | ||
| 9 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 10 | ; | ||
| 11 | ; Module: EKBD - basic keyboard handler for error handler routine | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date : June 10,1986 | ||
| 16 | ; | ||
| 17 | ; Author: | ||
| 18 | ; | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; CHANGES: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION DESCRIPTION | ||
| 24 | ; -------- -------- ------------------------------------------------------ | ||
| 25 | ; 06/10/86 Original | ||
| 26 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 27 | ; 07/06/86 0.04 Changed assumes to DGROUP | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; | ||
| 31 | ; Functional description: Return keyboard code while ignoring any break | ||
| 32 | ; or command codes. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | page | ||
| 36 | .386P | ||
| 37 | ; | ||
| 38 | include vdmseg.inc | ||
| 39 | include kbd.inc | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; Public Declarations | ||
| 42 | ;****************************************************************************** | ||
| 43 | ; | ||
| 44 | public egetc ; get a character | ||
| 45 | public WaitKBD ; wait for keyboard ready | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; Externs | ||
| 48 | ;****************************************************************************** | ||
| 49 | _TEXT segment | ||
| 50 | _TEXT ends | ||
| 51 | |||
| 52 | _DATA segment | ||
| 53 | _DATA ends | ||
| 54 | ; | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; Equates | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; | ||
| 59 | ; | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; LOCAL DATA | ||
| 62 | ;****************************************************************************** | ||
| 63 | _DATA segment | ||
| 64 | _DATA ends | ||
| 65 | ; | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; | ||
| 68 | ; egetc - read a character from keyboard | ||
| 69 | ; | ||
| 70 | ; entry: NONE | ||
| 71 | ; | ||
| 72 | ; exit: al = make code | ||
| 73 | ; ZF = 0 | ||
| 74 | ; | ||
| 75 | ; or ZF = 1 if no code available | ||
| 76 | ; | ||
| 77 | ; used: none | ||
| 78 | ; | ||
| 79 | ; stack: | ||
| 80 | ; | ||
| 81 | ;****************************************************************************** | ||
| 82 | _TEXT segment | ||
| 83 | ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP | ||
| 84 | egetc proc near | ||
| 85 | ; | ||
| 86 | in al,KbStatus ; get status | ||
| 87 | test al,1 ; q: is there anything out there? | ||
| 88 | jz kret ; n: return | ||
| 89 | ; ; y: disable keyboard | ||
| 90 | call WaitKBD ; wait til 8042 ready for input | ||
| 91 | mov al,0adh ; disable keyboard interface | ||
| 92 | out KbStatus,al | ||
| 93 | in al,KbData ; get character | ||
| 94 | cmp al,7fh ; q: break or control word? | ||
| 95 | jae ign_chr ; y: ignore it | ||
| 96 | cmp al,80h ; clear ZF | ||
| 97 | jmp enaKB ; go enable keyboard | ||
| 98 | ign_chr: | ||
| 99 | mov al,0 ; return an invalid character | ||
| 100 | ; but preserve ZF | ||
| 101 | enaKB: | ||
| 102 | pushf ; save flags | ||
| 103 | push ax ; save character | ||
| 104 | call WaitKBD | ||
| 105 | mov al,0aeh ; enable keyboard | ||
| 106 | out KbStatus,al | ||
| 107 | pop ax | ||
| 108 | popf | ||
| 109 | kret: | ||
| 110 | ret | ||
| 111 | egetc endp | ||
| 112 | ; | ||
| 113 | ;****************************************************************************** | ||
| 114 | ; | ||
| 115 | ; WaitKBD - wait for status to indicate ready for new command | ||
| 116 | ; | ||
| 117 | ; entry: NONE | ||
| 118 | ; | ||
| 119 | ; exit: NONE | ||
| 120 | ; | ||
| 121 | ; used: al | ||
| 122 | ; | ||
| 123 | ; stack: | ||
| 124 | ; | ||
| 125 | ;****************************************************************************** | ||
| 126 | WaitKBD proc near | ||
| 127 | push cx | ||
| 128 | xor cx,cx ; do 65536 times | ||
| 129 | wait: | ||
| 130 | in al,KbStatus | ||
| 131 | test al,BufFull ; q: busy? | ||
| 132 | loopnz wait ; y: try again | ||
| 133 | ; | ||
| 134 | pop cx ; n: return | ||
| 135 | ret | ||
| 136 | WaitKBD endp | ||
| 137 | |||
| 138 | _TEXT ENDS | ||
| 139 | END | ||
diff --git a/v4.0/src/MEMM/MEMM/ELIM.INC b/v4.0/src/MEMM/MEMM/ELIM.INC new file mode 100644 index 0000000..47f0bc0 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ELIM.INC | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ELIM.INC - include for LIM I/O traps (DMA ports) | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: April 9, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 04/09/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; 07/01/86 0.03 DMA trapping related equates added | ||
| 26 | ; | ||
| 27 | ; DATE AUTHOR DESCRIPTION | ||
| 28 | ; ------- -------- ------------------------------------------------------- | ||
| 29 | ; 06/21/88 ISP Removed the Intel Above Board Port Definitions | ||
| 30 | ; 07/27/88 JHB Added Channel 4 ports, ports for Mode Regs and changed | ||
| 31 | ; DMARegRec and DMARegBuf structure definitions - lifted | ||
| 32 | ; from vdmad.inc in Win386/2.03. | ||
| 33 | ; - Jaywant H Bharadwaj | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ifndef INC_LIST | ||
| 37 | .xlist | ||
| 38 | endif | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ; DMA related ports | ||
| 42 | ; | ||
| 43 | DMA_P0 equ 0087h ; DMA page register for Channel 0 | ||
| 44 | DMA_P1 equ 0083h ; DMA page register for Channel 1 | ||
| 45 | DMA_P2 equ 0081h ; DMA page register for Channel 2 | ||
| 46 | DMA_P3 equ 0082h ; DMA page register for Channel 3 | ||
| 47 | DMA_P5 equ 008Bh ; DMA page register for Channel 5 | ||
| 48 | DMA_P6 equ 0089h ; DMA page register for Channel 6 | ||
| 49 | DMA_P7 equ 008Ah ; DMA page register for Channel 7 | ||
| 50 | DMA_P4 equ 0080h ; dummy page reg for channel 4 | ||
| 51 | |||
| 52 | DMA_B0 equ 0000h ; DMA base register for Channel 0 | ||
| 53 | DMA_C0 equ 0001h ; DMA count register for Channel 0 | ||
| 54 | DMA_B1 equ 0002h ; DMA base register for Channel 1 | ||
| 55 | DMA_C1 equ 0003h ; DMA count register for Channel 1 | ||
| 56 | DMA_B2 equ 0004h ; DMA base register for Channel 2 | ||
| 57 | DMA_C2 equ 0005h ; DMA count register for Channel 2 | ||
| 58 | DMA_B3 equ 0006h ; DMA base register for Channel 3 | ||
| 59 | DMA_C3 equ 0007h ; DMA count register for Channel 3 | ||
| 60 | DMA_B4 equ 00C0h ; DMA base register for Channel 4 | ||
| 61 | DMA_C4 equ 00C2h ; DMA count register for Channel 4 | ||
| 62 | DMA_B5 equ 00C4h ; DMA base register for Channel 5 | ||
| 63 | DMA_C5 equ 00C6h ; DMA count register for Channel 5 | ||
| 64 | DMA_B6 equ 00C8h ; DMA base register for Channel 6 | ||
| 65 | DMA_C6 equ 00CAh ; DMA count register for Channel 6 | ||
| 66 | DMA_B7 equ 00CCh ; DMA base register for Channel 7 | ||
| 67 | DMA_C7 equ 00CEh ; DMA count register for Channel 7 | ||
| 68 | |||
| 69 | DMA1_CLR_FF equ 000Ch ; clear flip-flop cmd for channels 0-3 | ||
| 70 | DMA2_CLR_FF equ 00D8h ; clear flip-flop cmd for channels 5-7 | ||
| 71 | |||
| 72 | |||
| 73 | DMA1_MODE equ 000Bh ; Mode register for channels 0-3 | ||
| 74 | DMA2_MODE equ 00D6h ; Mode register for channels 4-7 | ||
| 75 | |||
| 76 | DMA_M_CHANNEL equ 03h ; Mask for channel | ||
| 77 | DMA_M_OPERATION equ 0Ch ; Mask for operation | ||
| 78 | DMA_M_16BIT equ 040h ; 16bit transfers (PS/2 ext mode) | ||
| 79 | |||
| 80 | DMA_M_VERIFY equ 0 ; Verify operation | ||
| 81 | DMA_M_WRITE equ 4 ; Write | ||
| 82 | |||
| 83 | |||
| 84 | ;************************************************************************** | ||
| 85 | ; New defintions for DMARegRec and DMARegBuf - 7/27/88 | ||
| 86 | ; | ||
| 87 | ; | ||
| 88 | ; DMA Register Save Structure | ||
| 89 | ; | ||
| 90 | |||
| 91 | ; | ||
| 92 | ; note: the DMA code in ELIMTRAP.ASM is tuned to this structure's size = 16 | ||
| 93 | ; if you change the size, you had better change the code ! | ||
| 94 | ; LinAdr and PhysAdr have to be dwords | ||
| 95 | ; count though 16 bits long is left as a dword since the rest of the ported | ||
| 96 | ; 386 code is dependent on this structure being 16 bytes long. | ||
| 97 | ; | ||
| 98 | |||
| 99 | DMARegRec struc | ||
| 100 | DMALinAdr dd 00000000 ; Channel Linear Base Register | ||
| 101 | DMAPhyAdr dd 00000000 ; Channel Physical Base Register | ||
| 102 | DMACount dd 00000000 ; Channel Count Register | ||
| 103 | DMAPagePort db ? ; byte addr of page reg | ||
| 104 | DMABasePort db ? ; byte addr of base addr reg | ||
| 105 | DMACntPort db ? ; byte addr of cnt addr reg | ||
| 106 | DMAMode db ? ; Mode register | ||
| 107 | DMARegRec ends | ||
| 108 | |||
| 109 | DMARegBuf struc | ||
| 110 | Chnl0 db (size DMARegRec - 4) dup (00), DMA_P0, DMA_B0, DMA_C0, 0 | ||
| 111 | Chnl1 db (size DMARegRec - 4) dup (00), DMA_P1, DMA_B1, DMA_C1, 0 | ||
| 112 | Chnl2 db (size DMARegRec - 4) dup (00), DMA_P2, DMA_B2, DMA_C2, 0 | ||
| 113 | Chnl3 db (size DMARegRec - 4) dup (00), DMA_P3, DMA_B3, DMA_C3, 0 | ||
| 114 | Chnl4 db (size DMARegRec - 4) dup (00), DMA_P4, DMA_B4, DMA_C4, DMA_M_16BIT | ||
| 115 | Chnl5 db (size DMARegRec - 4) dup (00), DMA_P5, DMA_B5, DMA_C5, DMA_M_16BIT | ||
| 116 | Chnl6 db (size DMARegRec - 4) dup (00), DMA_P6, DMA_B6, DMA_C6, DMA_M_16BIT | ||
| 117 | Chnl7 db (size DMARegRec - 4) dup (00), DMA_P7, DMA_B7, DMA_C7, DMA_M_16BIT | ||
| 118 | DMAFF1 db 00 ; Controller 1 FlipFlop State | ||
| 119 | DMAFF2 db 00 ; Controller 2 FlipFlop State | ||
| 120 | DMA_Xfun db 0 ; Extended Operation Function | ||
| 121 | DMA_Xchn db 0 ; Extended Operation Channel | ||
| 122 | DMARegBuf ends | ||
| 123 | |||
| 124 | DMAREG_CTRL2_INDEX equ 4 * 2 ; 2 * 1st channel # on 2nd cntlr | ||
| 125 | |||
| 126 | |||
| 127 | .list ; end of ELIM.INC | ||
| 128 | |||
diff --git a/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM b/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM new file mode 100644 index 0000000..d431f0b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ELIMFUNC.ASM | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title ELIMFUNC - MEMM functions module | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: ELIMFUNC - entry point for VDM functions | ||
| 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/24/86 Original From EMML LIM driver. | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; 07/05/86 0.04 Added segment R_CODE | ||
| 29 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 30 | ; 07/10/86 0.05 jmp $+2 before "POPF" | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; Functional Description: | ||
| 34 | ; This module contains the ON/OFF functionality code for activating/ | ||
| 35 | ; deactivating EMM386 from DOS. Functions in _TEXT to reduce code in | ||
| 36 | ; R_CODE segment. | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | .lfcond | ||
| 40 | .386p | ||
| 41 | page | ||
| 42 | ;****************************************************************************** | ||
| 43 | ; P U B L I C D E C L A R A T I O N S | ||
| 44 | ;****************************************************************************** | ||
| 45 | ; | ||
| 46 | public ELIM_Entry | ||
| 47 | public EFunTab | ||
| 48 | public EFUN_CNT | ||
| 49 | ; | ||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; L O C A L C O N S T A N T S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | include vdmseg.inc | ||
| 56 | |||
| 57 | FALSE equ 0 | ||
| 58 | TRUE equ not FALSE | ||
| 59 | |||
| 60 | ;****************************************************************************** | ||
| 61 | ; E X T E R N A L R E F E R E N C E S | ||
| 62 | ;****************************************************************************** | ||
| 63 | ; | ||
| 64 | _DATA segment | ||
| 65 | extrn Active_Status:byte | ||
| 66 | extrn Auto_Mode:byte | ||
| 67 | _DATA ends | ||
| 68 | |||
| 69 | _TEXT segment | ||
| 70 | extrn _AutoUpdate:near ; update auto mode status | ||
| 71 | extrn GoVirtual:near | ||
| 72 | extrn RRProc:near ; Return processor to real mode(RRTrap) | ||
| 73 | _TEXT ends | ||
| 74 | |||
| 75 | page | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; S E G M E N T D E F I N I T I O N | ||
| 78 | ;****************************************************************************** | ||
| 79 | ; | ||
| 80 | ;****************************************************************************** | ||
| 81 | ; | ||
| 82 | ; Code Segment R_CODE | ||
| 83 | ; | ||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | R_CODE segment | ||
| 87 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 88 | ; | ||
| 89 | ; ELIM functions table - far calls | ||
| 90 | ; | ||
| 91 | EFunTab label dword | ||
| 92 | dw offset E_GetStatus | ||
| 93 | dw seg _TEXT | ||
| 94 | |||
| 95 | dw offset E_ONOFF | ||
| 96 | dw seg _TEXT | ||
| 97 | |||
| 98 | EFUN_CNT equ ($-EFunTab)/4 | ||
| 99 | |||
| 100 | page | ||
| 101 | ;****************************************************************************** | ||
| 102 | ; ELIM_Entry - entry point for general ELIM functions | ||
| 103 | ; | ||
| 104 | ; THIS IS A FAR CALL ROUTINE | ||
| 105 | ; | ||
| 106 | ; ENTRY: REAL or VIRTUAL mode only | ||
| 107 | ; AH = 0 => get current status of VDM/EMM386 | ||
| 108 | ; AH = 1 => ON/OFF/AUTO | ||
| 109 | ; | ||
| 110 | ; EXIT: EMM386 is activated/deactivated if possible | ||
| 111 | ; NC => no errors. | ||
| 112 | ; CY => ERROR occured. | ||
| 113 | ; AH = error number | ||
| 114 | ; AH= 01 =>invalid function. | ||
| 115 | ; | ||
| 116 | ; USED: none | ||
| 117 | ; | ||
| 118 | ;****************************************************************************** | ||
| 119 | ELIM_Entry proc far | ||
| 120 | ; | ||
| 121 | push bx | ||
| 122 | push ds | ||
| 123 | ; | ||
| 124 | mov bx,seg DGROUP | ||
| 125 | mov ds,bx | ||
| 126 | ; | ||
| 127 | cmp ah,EFUN_CNT ;Q: valid function # | ||
| 128 | jae EE_inv_func ; N: return error | ||
| 129 | xor bx,bx ; Y: exec function | ||
| 130 | mov bl,ah ; bx = function # | ||
| 131 | shl bx,2 ; dword index | ||
| 132 | call CS:EFunTab[bx] ; call the function | ||
| 133 | ; | ||
| 134 | EE_exit: | ||
| 135 | pop ds | ||
| 136 | pop bx | ||
| 137 | ret | ||
| 138 | ; | ||
| 139 | EE_inv_func: | ||
| 140 | mov ah,01 | ||
| 141 | stc | ||
| 142 | jmp short EE_exit | ||
| 143 | ; | ||
| 144 | ELIM_Entry endp | ||
| 145 | |||
| 146 | R_CODE ends | ||
| 147 | |||
| 148 | page | ||
| 149 | ;****************************************************************************** | ||
| 150 | ; | ||
| 151 | ; Code Segment _TEXT | ||
| 152 | ; | ||
| 153 | ;****************************************************************************** | ||
| 154 | _TEXT segment | ||
| 155 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 156 | |||
| 157 | ;****************************************************************************** | ||
| 158 | ; E_GetStatus - get ELIM/VDM status | ||
| 159 | ; | ||
| 160 | ; ENTRY: AH = 0 | ||
| 161 | ; DS = DGROUP | ||
| 162 | ; | ||
| 163 | ; EXIT: AH = 0 => ELIM ON | ||
| 164 | ; = 1 => ELIM OFF | ||
| 165 | ; = 2 => ELIM in AUTO mode (ON) | ||
| 166 | ; = 3 => ELIM in AUTO mode (OFF) | ||
| 167 | ; | ||
| 168 | ; USED: none | ||
| 169 | ; | ||
| 170 | ;****************************************************************************** | ||
| 171 | E_GetStatus proc far | ||
| 172 | ; | ||
| 173 | xor ah,ah ; init to on | ||
| 174 | cmp [Auto_Mode],0 ; Q: auto mode ? | ||
| 175 | je not_auto ; N: try on/off | ||
| 176 | mov ah,2 ; Y: indicate as such | ||
| 177 | not_auto: | ||
| 178 | cmp [Active_Status],0 ;Q: is ELIM active ? | ||
| 179 | jne EGS_exit ; Y: exit with status = 0/2 | ||
| 180 | inc ah ; N: exit with status = 1/3 | ||
| 181 | EGS_exit: | ||
| 182 | ret | ||
| 183 | ; | ||
| 184 | E_GetStatus endp | ||
| 185 | |||
| 186 | ;****************************************************************************** | ||
| 187 | ; E_ONOFF - general ON/OFF code for ELIM | ||
| 188 | ; | ||
| 189 | ; ENTRY: AH = 1 | ||
| 190 | ; AL = 0 => ON | ||
| 191 | ; AL = 1 => OFF | ||
| 192 | ; AL = 2 => AUTO | ||
| 193 | ; DS = DGROUP | ||
| 194 | ; | ||
| 195 | ; EXIT: Virtual mode and ELIM ON | ||
| 196 | ; OR Real mode and ELIM OFF | ||
| 197 | ; | ||
| 198 | ; USED: none | ||
| 199 | ; | ||
| 200 | ;****************************************************************************** | ||
| 201 | E_ONOFF proc far | ||
| 202 | ; | ||
| 203 | cmp al,0 ;Q: turn it on ? | ||
| 204 | jne EOO_OFF ; N: check for OFF/AUTO | ||
| 205 | cmp [Active_Status],0 ; Y: Q: is it already active ? | ||
| 206 | jne EOO_AUTO_OFF ; Y: then just leave | ||
| 207 | mov [Active_Status],1 ; N: then go to virtual mode | ||
| 208 | mov [Auto_Mode],0 ; and clear auto mode | ||
| 209 | call GoVirtual | ||
| 210 | jmp short EOO_OK | ||
| 211 | EOO_OFF: | ||
| 212 | cmp al,1 ;Q: turn it off ? | ||
| 213 | jne EOO_AUTO ; N: check for AUTO mode | ||
| 214 | |||
| 215 | ; | ||
| 216 | ; we are not providing the ability to turn emm off. | ||
| 217 | ; | ||
| 218 | ; cmp [Active_Status],0 ; Y: Q: is it already OFF ? | ||
| 219 | ; je EOO_AUTO_OFF ; Y: then just leave | ||
| 220 | ; mov [Active_Status],0 ; N: then go to real mode | ||
| 221 | ; mov [Auto_Mode],0 ; and clear auto mode | ||
| 222 | ; call RRProc ; put processor in real mode | ||
| 223 | ; jmp short EOO_OK | ||
| 224 | |||
| 225 | jmp short EOO_inv | ||
| 226 | |||
| 227 | |||
| 228 | EOO_AUTO_OFF: | ||
| 229 | ; cmp [Auto_Mode],0 ; q: auto mode already off? | ||
| 230 | ; jz EOO_OK ; y: forget it | ||
| 231 | ; mov [Auto_Mode],0 ; n: clear it | ||
| 232 | ; jmp short EOO_OK ; and update status | ||
| 233 | |||
| 234 | jmp short EOO_inv | ||
| 235 | |||
| 236 | |||
| 237 | EOO_AUTO: | ||
| 238 | cmp al,2 ;Q: go to auto mode ? | ||
| 239 | jne EOO_inv ; N: invalid function | ||
| 240 | ; cmp [Auto_Mode],0 ; Y: Q: is it already in auto mode | ||
| 241 | ; jne EOO_OK ; Y: then just leave | ||
| 242 | ; mov [Auto_Mode],1 ; N: then go to auto mode | ||
| 243 | ; call _AutoUpdate ; | ||
| 244 | |||
| 245 | jmp short EOO_inv | ||
| 246 | ; | ||
| 247 | ; leave with no errors | ||
| 248 | ; | ||
| 249 | EOO_OK: | ||
| 250 | clc | ||
| 251 | |||
| 252 | EOO_exit: | ||
| 253 | ret | ||
| 254 | ; | ||
| 255 | ; invalide ON/OFF/AUTO function call | ||
| 256 | ; | ||
| 257 | EOO_inv: | ||
| 258 | mov ah,1 | ||
| 259 | stc | ||
| 260 | jmp short EOO_exit | ||
| 261 | ; | ||
| 262 | E_ONOFF endp | ||
| 263 | |||
| 264 | ; | ||
| 265 | _TEXT ends | ||
| 266 | |||
| 267 | end | ||
| 268 | |||
diff --git a/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM b/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM new file mode 100644 index 0000000..1036c33 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ELIMTRAP.ASM | |||
| @@ -0,0 +1,1560 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | title DMATRAP.ASM - Trap handlers for DMA ports | ||
| 5 | ;****************************************************************************** | ||
| 6 | ; | ||
| 7 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 8 | ; | ||
| 9 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 10 | ; | ||
| 11 | ; Module: DMATRAP.ASM - Trap Handlers for DMA ports | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: April 9, 1986 | ||
| 16 | ; | ||
| 17 | ; Author: | ||
| 18 | ; | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; Change log: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION DESCRIPTION | ||
| 24 | ; -------- -------- ------------------------------------------------------- | ||
| 25 | ; 04/09/86 Original | ||
| 26 | ; 06/18/86 0.01 Modified LIM_Map to handle all 4 boards and call | ||
| 27 | ; page mapping routine in EMMLIB.LIB | ||
| 28 | ; 06/27/86 0.02 Made _page_frame_address indexing dword (was word) | ||
| 29 | ; | ||
| 30 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 31 | ; 07/01/86 0.03 Added DMA support routines | ||
| 32 | ; 07/02/86 0.03 Fixed CNT size vs. length problem | ||
| 33 | ; 07/06/86 0.04 Made _pft386 a ptr to _pft386 array | ||
| 34 | ; 07/06/86 0.04 now sets _window array also | ||
| 35 | ; 08/11/86 0.05 moved IO_Trap code for LIM DMA trapping here | ||
| 36 | ; 06/09/88 remove IOT_LIM, LIMMap, and InitELIM since we don't | ||
| 37 | ; have any EMM hardware to trap and emulate now (Paulch) | ||
| 38 | ; 07/26/88 reintroduced initelim removing iab port trap (ISP) | ||
| 39 | ; | ||
| 40 | ; 07/27/88 Started rewriting the DMA port trap handlers - similar to the | ||
| 41 | ; code in VDMAD.ASM in Win/386 V2.03 | ||
| 42 | ; - Jaywant H Bharadwaj | ||
| 43 | ; | ||
| 44 | ;***************************************************************************** | ||
| 45 | |||
| 46 | |||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | ; Functional Description: | ||
| 50 | ; | ||
| 51 | ; Monitors writes/reads to the DMA ports. | ||
| 52 | ; Reads are simple - return the value saved in DMARegSav structure. | ||
| 53 | ; On a write to Page/Base/count Reg port - | ||
| 54 | ; user specifies a linear address. DMAs can handle only physical addresses. | ||
| 55 | ; Therefore, the actual physical address has to be written into the Page and | ||
| 56 | ; base Address Reg. Also the DMA transfer area may not be physically contiguous. | ||
| 57 | ; If it isn't we should remap the linear address so that it is physically | ||
| 58 | ; contiguous. | ||
| 59 | ; | ||
| 60 | ; We never know when a DMA is started. Hence on every access to the Page/Base | ||
| 61 | ; or count Register we make sure that the linear address specified by the user | ||
| 62 | ; maps to a physical address which is contiguous over the DMA transfer area. | ||
| 63 | ; This has to be done even if the count register is altered since the user | ||
| 64 | ; might be relying on the previous contents of Page/Addr Regs which may not be | ||
| 65 | ; contiguous anymore. | ||
| 66 | ; | ||
| 67 | ; All routines except InitDMA are entered through protected mode only. | ||
| 68 | ; | ||
| 69 | ;****************************************************************************** | ||
| 70 | |||
| 71 | .lfcond ; list false conditionals | ||
| 72 | .386p | ||
| 73 | |||
| 74 | page | ||
| 75 | ;****************************************************************************** | ||
| 76 | ; P U B L I C D E C L A R A T I O N S | ||
| 77 | ;****************************************************************************** | ||
| 78 | |||
| 79 | ; | ||
| 80 | ; routines called from C | ||
| 81 | ; | ||
| 82 | public _GetPte | ||
| 83 | public _SetPte | ||
| 84 | public _GetCRSEntry | ||
| 85 | public _GetDMALinAdr | ||
| 86 | public _Exchange16K | ||
| 87 | public _FatalError | ||
| 88 | |||
| 89 | public InitELIM ; initialization routine for LIMulator | ||
| 90 | public InitDMA ; init DMA register save area | ||
| 91 | public DMARegSav | ||
| 92 | public _DMA_Pages | ||
| 93 | public DMA_Pages | ||
| 94 | public _DMA_PAGE_COUNT | ||
| 95 | public DMA_PAGE_COUNT | ||
| 96 | |||
| 97 | |||
| 98 | |||
| 99 | public DMA_DMAFixup | ||
| 100 | public DMABase0 | ||
| 101 | public DMABase1 | ||
| 102 | public DMABase2 | ||
| 103 | public DMABase3 | ||
| 104 | public DMABase5 | ||
| 105 | public DMABase6 | ||
| 106 | public DMABase7 | ||
| 107 | |||
| 108 | public DMACnt0 | ||
| 109 | public DMACnt1 | ||
| 110 | public DMACnt2 | ||
| 111 | public DMACnt3 | ||
| 112 | public DMACnt5 | ||
| 113 | public DMACnt6 | ||
| 114 | public DMACnt7 | ||
| 115 | public DMAPg0 | ||
| 116 | public DMAPg1 | ||
| 117 | public DMAPg2 | ||
| 118 | public DMAPg3 | ||
| 119 | public DMAPg5 | ||
| 120 | public DMAPg6 | ||
| 121 | public DMAPg7 | ||
| 122 | public DMAClrFF1 | ||
| 123 | public DMAClrFF2 | ||
| 124 | public DMAMode1 | ||
| 125 | public DMAMode2 | ||
| 126 | |||
| 127 | |||
| 128 | page | ||
| 129 | ;****************************************************************************** | ||
| 130 | ; L O C A L C O N S T A N T S | ||
| 131 | ;****************************************************************************** | ||
| 132 | ; | ||
| 133 | include VDMseg.inc | ||
| 134 | include VDMsel.inc | ||
| 135 | include desc.inc | ||
| 136 | include elim.inc | ||
| 137 | include mach_id.inc | ||
| 138 | include page.inc | ||
| 139 | include oemdep.inc | ||
| 140 | include instr386.inc | ||
| 141 | include vm386.inc | ||
| 142 | include emmdef.inc | ||
| 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 | ;****************************************************************************** | ||
| 155 | Get_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 | ; | ||
| 163 | ; InitDMARegSav - MACRO for initialising save area for channels | ||
| 164 | ; | ||
| 165 | ; ENTRY: chan_num = channel number (1,2,3,5,6,7) | ||
| 166 | ; ES -> DGROUP | ||
| 167 | ; | ||
| 168 | ;----------------------------------------------------------------------------- | ||
| 169 | |||
| 170 | InitDMARegSav MACRO chan_num | ||
| 171 | |||
| 172 | lea di,[DMARegSav.Chnl&chan_num] ; pt to channel's save area | ||
| 173 | |||
| 174 | xor eax, eax | ||
| 175 | in al,DMA_P&chan_num ; page register for channel | ||
| 176 | jmp $+2 | ||
| 177 | jmp $+2 ; timing | ||
| 178 | shl eax,16 ; high EAX = high word of linear addr | ||
| 179 | |||
| 180 | ; flip-flop already reset by the caller | ||
| 181 | |||
| 182 | in al,DMA_B&chan_num ; get low byte of base | ||
| 183 | jmp $+2 | ||
| 184 | jmp $+2 ; timing | ||
| 185 | mov ah,al | ||
| 186 | in al,DMA_B&chan_num ; get high byte of base | ||
| 187 | xchg ah,al | ||
| 188 | ; EAX = LINEAR BASE address | ||
| 189 | |||
| 190 | stosd ; store LINEAR BASE address | ||
| 191 | |||
| 192 | stosd ; store PHYSICAL BASE address | ||
| 193 | |||
| 194 | xor eax, eax ; clear EAX | ||
| 195 | jmp $+2 | ||
| 196 | jmp $+2 ; timing | ||
| 197 | in al,DMA_C&chan_num ; get low byte of count | ||
| 198 | jmp $+2 | ||
| 199 | jmp $+2 ; timing | ||
| 200 | mov ah,al | ||
| 201 | in al,DMA_C&chan_num ; get high byte of count | ||
| 202 | xchg ah,al | ||
| 203 | ; EAX = count | ||
| 204 | |||
| 205 | stosd ; store count | ||
| 206 | |||
| 207 | add di, 4 ; skip 4 bytes - 3 ports+mode byte | ||
| 208 | |||
| 209 | ENDM | ||
| 210 | |||
| 211 | |||
| 212 | ;****************************************************************************** | ||
| 213 | ; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address | ||
| 214 | ; | ||
| 215 | ; ENTRY: 386 PROTECTED MODE | ||
| 216 | ; DS -> DGROUP | ||
| 217 | ; ES -> DGROUP | ||
| 218 | ; EAX - Word Address | ||
| 219 | ; | ||
| 220 | ; EXIT: EAX - Byte address | ||
| 221 | ; | ||
| 222 | ; USED: | ||
| 223 | ;------------------------------------------------------------------------------ | ||
| 224 | DMA_WADDR_TO_BADDR MACRO | ||
| 225 | LOCAL Not_AT | ||
| 226 | |||
| 227 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 228 | jbe short Not_AT ; If running on EBIOS machine | ||
| 229 | |||
| 230 | ror eax,16 ; AX = high word | ||
| 231 | shr al,1 ; adjust for D0 null in page reg | ||
| 232 | rol eax,17 ; EAX = address w/ adjust for | ||
| 233 | ; 'A0' offset | ||
| 234 | Not_At: | ||
| 235 | shl ecx, 1 ; Adjust for word units | ||
| 236 | ENDM | ||
| 237 | |||
| 238 | |||
| 239 | ;****************************************************************************** | ||
| 240 | ; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address | ||
| 241 | ; | ||
| 242 | ; ENTRY: 386 PROTECTED MODE | ||
| 243 | ; DS -> DGROUP | ||
| 244 | ; ES -> DGROUP | ||
| 245 | ; EAX - Word Address | ||
| 246 | ; | ||
| 247 | ; EXIT: EAX - Byte address | ||
| 248 | ; | ||
| 249 | ; USED: | ||
| 250 | ;------------------------------------------------------------------------------ | ||
| 251 | DMA_BADDR_TO_WADDR MACRO | ||
| 252 | LOCAL Not_AT | ||
| 253 | |||
| 254 | cmp [ROM_BIOS_Machine_ID], RBMI_Sys80 | ||
| 255 | jbe short Not_AT ; If running on EBIOS machine | ||
| 256 | |||
| 257 | shr eax, 1 ; Adjust for implied 'A0' | ||
| 258 | push ax ; Save A16-A1 | ||
| 259 | xor ax, ax | ||
| 260 | shl eax, 1 ; Adjust for unused Pg Reg D0 | ||
| 261 | pop ax ; Restore A16-A1 | ||
| 262 | Not_At: | ||
| 263 | ENDM | ||
| 264 | |||
| 265 | ;****************************************************************************** | ||
| 266 | ; E X T E R N A L R E F E R E N C E S | ||
| 267 | ;****************************************************************************** | ||
| 268 | |||
| 269 | _DATA segment | ||
| 270 | extrn ROM_BIOS_Machine_ID:byte | ||
| 271 | extrn _page_frame_base:word | ||
| 272 | extrn CurRegSet:word | ||
| 273 | extrn Page_Dir:word | ||
| 274 | SaveAL db ? | ||
| 275 | _DATA ends | ||
| 276 | |||
| 277 | _TEXT segment | ||
| 278 | |||
| 279 | extrn PortTrap:near ; set port bit in I/O bit Map | ||
| 280 | extrn MapLinear:near | ||
| 281 | extrn ErrHndlr:near | ||
| 282 | ; | ||
| 283 | ; Swap pages so that DMA Xfer area is physically contiguous. | ||
| 284 | ; defined in mapdma.c | ||
| 285 | ; | ||
| 286 | extrn _SwapDMAPages:near | ||
| 287 | |||
| 288 | _TEXT ends | ||
| 289 | |||
| 290 | ;****************************************************************************** | ||
| 291 | ; S E G M E N T D E F I N I T I O N | ||
| 292 | ;****************************************************************************** | ||
| 293 | |||
| 294 | _DATA segment | ||
| 295 | |||
| 296 | DMARegSav DMARegBuf <> ; DMA Register buffer | ||
| 297 | |||
| 298 | DMAP_Page label word | ||
| 299 | ; dw DMA_P0 ; DMA page registers | ||
| 300 | dw DMA_P1 | ||
| 301 | dw DMA_P2 | ||
| 302 | dw DMA_P3 | ||
| 303 | dw DMA_P5 | ||
| 304 | dw DMA_P6 | ||
| 305 | dw DMA_P7 | ||
| 306 | ; dw DMA_P4 | ||
| 307 | ; dw DMA_P0+10h ; page regs mapped to here also | ||
| 308 | dw DMA_P1+10h | ||
| 309 | dw DMA_P2+10h | ||
| 310 | dw DMA_P3+10h | ||
| 311 | dw DMA_P5+10h | ||
| 312 | dw DMA_P6+10h | ||
| 313 | dw DMA_P7+10h | ||
| 314 | ; dw DMA_P4+10h | ||
| 315 | DMAP_Addr label word | ||
| 316 | ; dw DMA_B0 ; DMA base registers | ||
| 317 | dw DMA_B1 | ||
| 318 | dw DMA_B2 | ||
| 319 | dw DMA_B3 | ||
| 320 | dw DMA_B5 | ||
| 321 | dw DMA_B6 | ||
| 322 | dw DMA_B7 | ||
| 323 | DMAP_Count label word | ||
| 324 | ; dw DMA_C0 ; DMA count registers | ||
| 325 | dw DMA_C1 | ||
| 326 | dw DMA_C2 | ||
| 327 | dw DMA_C3 | ||
| 328 | dw DMA_C5 | ||
| 329 | dw DMA_C6 | ||
| 330 | dw DMA_C7 | ||
| 331 | dw DMA1_CLR_FF ; reset flip-flop commands | ||
| 332 | dw DMA2_CLR_FF | ||
| 333 | DMAP_Mode label word | ||
| 334 | dw DMA1_MODE | ||
| 335 | dw DMA2_MODE | ||
| 336 | |||
| 337 | LIMDMAP_CNT = ($ - DMAP_Page) / 2 | ||
| 338 | ; | ||
| 339 | ; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386. | ||
| 340 | ; To access actual entry in pft386 you need to multiply index by 4. | ||
| 341 | ; If eight contingous 16k EMM pages are not available - the unavailable | ||
| 342 | ; entries are left at NULL_PAGE. | ||
| 343 | ; This array should be initialized at boot time. | ||
| 344 | ; | ||
| 345 | _DMA_Pages LABEL WORD | ||
| 346 | DMA_Pages dw 8 dup (NULL_PAGE) ; null for start | ||
| 347 | _DMA_PAGE_COUNT LABEL WORD | ||
| 348 | DMA_PAGE_COUNT dw 0 ; number of above initialised | ||
| 349 | |||
| 350 | |||
| 351 | _DATA ends | ||
| 352 | |||
| 353 | page | ||
| 354 | |||
| 355 | ;------------------------------------------------------------------------------ | ||
| 356 | |||
| 357 | _TEXT segment | ||
| 358 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 359 | |||
| 360 | ;****************************************************************************** | ||
| 361 | ; | ||
| 362 | ; InitDMA - initialize internal values for DMA registers of each channel | ||
| 363 | ; | ||
| 364 | ; ENTRY: Real Mode | ||
| 365 | ; DS = DGROUP | ||
| 366 | ; | ||
| 367 | ; EXIT: Real Mode | ||
| 368 | ; DGROUP:[DMARegSav] = DMA register save area initialized | ||
| 369 | ; | ||
| 370 | ;------------------------------------------------------------------------------ | ||
| 371 | |||
| 372 | InitDMA proc near | ||
| 373 | |||
| 374 | push eax | ||
| 375 | push di | ||
| 376 | push es | ||
| 377 | |||
| 378 | pushf | ||
| 379 | cli | ||
| 380 | cld | ||
| 381 | |||
| 382 | push ds | ||
| 383 | pop es ; ES = DGROUP | ||
| 384 | |||
| 385 | xor al,al | ||
| 386 | out DMA1_CLR_FF, al ; clear FF on first controller | ||
| 387 | mov [DMARegSav.DMAFF1], al ; reset S/W FF | ||
| 388 | jmp $+2 | ||
| 389 | jmp $+2 ; timing | ||
| 390 | ; | ||
| 391 | ; initialize regs for channels 1,2,3 | ||
| 392 | ; | ||
| 393 | InitDMARegSav 1 | ||
| 394 | InitDMARegSav 2 | ||
| 395 | InitDMARegSav 3 | ||
| 396 | |||
| 397 | xor al,al | ||
| 398 | out DMA2_CLR_FF, al ; clear FF on second controller | ||
| 399 | mov [DMARegSav.DMAFF2], al ; reset S/W FF | ||
| 400 | jmp $+2 | ||
| 401 | jmp $+2 ; timing | ||
| 402 | ; | ||
| 403 | ; initialize regs for channels 5,6,7 | ||
| 404 | ; | ||
| 405 | InitDMARegSav 5 | ||
| 406 | InitDMARegSav 6 | ||
| 407 | InitDMARegSav 7 | ||
| 408 | |||
| 409 | popf | ||
| 410 | pop es | ||
| 411 | pop di | ||
| 412 | pop eax | ||
| 413 | ret | ||
| 414 | |||
| 415 | InitDMA endp | ||
| 416 | |||
| 417 | ;****************************************************************************** | ||
| 418 | ; | ||
| 419 | ; DMABase(0-7) - Write/Read DMA Channel N Base Register | ||
| 420 | ; | ||
| 421 | ; ENTRY: | ||
| 422 | ; AL = byte to output to port | ||
| 423 | ; BX = port * 2 | ||
| 424 | ; DH = 0 => Emulate Input | ||
| 425 | ; <>0 => Emulate Output | ||
| 426 | ; | ||
| 427 | ; EXIT: | ||
| 428 | ; AL = emulated input/output value from port. | ||
| 429 | ; CLC => I/O emulated or performed | ||
| 430 | ; | ||
| 431 | ;------------------------------------------------------------------------------ | ||
| 432 | DMABase0to7 proc near | ||
| 433 | |||
| 434 | DMABase4: ; I/O port C0h | ||
| 435 | DMABase5: ; I/O port C4h | ||
| 436 | DMABase6: ; I/O port C8h | ||
| 437 | DMABase7: ; I/O port CCh | ||
| 438 | push ax | ||
| 439 | push bx | ||
| 440 | push cx | ||
| 441 | push dx | ||
| 442 | push si | ||
| 443 | ; | ||
| 444 | ; Now, BX = port * 2 and DX = IO code | ||
| 445 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 446 | ; | ||
| 447 | xchg dx, bx | ||
| 448 | shr dx, 1 | ||
| 449 | xchg bh,bl ; move IO code to bh | ||
| 450 | |||
| 451 | mov si, dx | ||
| 452 | sub si, 0B0h ; SI = Channel * 4 | ||
| 453 | shl si, 2 ; SI = Channel * 16 | ||
| 454 | mov bl, [DMARegSav.DMAFF2] ; get flip-flop | ||
| 455 | xor [DMARegSav.DMAFF2], 1 ; and toggle it | ||
| 456 | jmp short DMABaseN ; | ||
| 457 | |||
| 458 | DMABase0: ; I/O port 00h | ||
| 459 | DMABase1: ; I/O port 02h | ||
| 460 | DMABase2: ; I/O port 04h | ||
| 461 | DMABase3: ; I/O port 06h | ||
| 462 | push ax | ||
| 463 | push bx | ||
| 464 | push cx | ||
| 465 | push dx | ||
| 466 | push si | ||
| 467 | ; | ||
| 468 | ; Now, BX = port * 2 and DX = IO code | ||
| 469 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 470 | ; | ||
| 471 | xchg dx, bx | ||
| 472 | shr dx, 1 | ||
| 473 | xchg bh,bl ; move IO code to bh | ||
| 474 | |||
| 475 | mov si, dx ; SI = Channel * 2 | ||
| 476 | shl si, 3 ; SI = Channel * 16 | ||
| 477 | mov bl, [DMARegSav.DMAFF1] ; get flip-flop | ||
| 478 | xor [DMARegSav.DMAFF1], 1 ; and toggle it | ||
| 479 | |||
| 480 | ; | ||
| 481 | ; FALL THROUGH!!! | ||
| 482 | ; | ||
| 483 | |||
| 484 | ;****************************************************************************** | ||
| 485 | ; | ||
| 486 | ; DMABaseN - Write/Read DMA Channel N Base Register | ||
| 487 | ; | ||
| 488 | ; ENTRY: As above plus | ||
| 489 | ; SI = 16 * channel # | ||
| 490 | ; | ||
| 491 | ;------------------------------------------------------------------------------ | ||
| 492 | DMABaseN: | ||
| 493 | and bl, 1 ; Look at bit0 only - safety | ||
| 494 | |||
| 495 | or bh,bh ;Q: Input ? | ||
| 496 | jz short Base_rd_port ; Y: do Read operation | ||
| 497 | ; N: save value "written" | ||
| 498 | mov [SaveAL], al ; save AL in Save area. | ||
| 499 | xor bh, bh ; Make BX = Flip Flop state | ||
| 500 | mov byte ptr DMARegSav.DMALinAdr[bx][si], al | ||
| 501 | |||
| 502 | in al, dx ; Just a Dummy I/O to | ||
| 503 | ; toggle the real flip-flop | ||
| 504 | ; to match DMAFF above | ||
| 505 | jmp $+2 | ||
| 506 | jmp $+2 | ||
| 507 | xor bl,1 ; and the s/w one | ||
| 508 | |||
| 509 | call DMA_DMAFixup ; Translate Lin to Phys | ||
| 510 | ; & Update DMARegSav | ||
| 511 | call DMA_WrtAdrReg ; emulate the write | ||
| 512 | jmp short DBExit | ||
| 513 | |||
| 514 | Base_rd_port: | ||
| 515 | in al, dx ; Toggle the real flop-flip | ||
| 516 | ; | ||
| 517 | ; bh is already zero, therefore BX = flip flop state | ||
| 518 | ; | ||
| 519 | mov al,byte ptr DMARegSav.DMALinAdr[bx][si] | ||
| 520 | mov [SaveAL], al | ||
| 521 | DBExit: | ||
| 522 | pop si | ||
| 523 | pop dx | ||
| 524 | pop cx | ||
| 525 | pop bx | ||
| 526 | pop ax | ||
| 527 | mov al, [SaveAL] | ||
| 528 | clc | ||
| 529 | ret | ||
| 530 | |||
| 531 | DMABase0to7 endp | ||
| 532 | |||
| 533 | page | ||
| 534 | |||
| 535 | ;****************************************************************************** | ||
| 536 | ; | ||
| 537 | ; DMACnt(0-7) - Write/Read DMA Channel N Count Register | ||
| 538 | ; | ||
| 539 | ;ENTRY: | ||
| 540 | ; AL = byte to output to port. | ||
| 541 | ; BX = port * 2 | ||
| 542 | ; DH = 0 => Emulate Input. | ||
| 543 | ; <>0 => Emulate Output. | ||
| 544 | ; | ||
| 545 | ;EXIT: | ||
| 546 | ; AL = emulated input/output value from port. | ||
| 547 | ; CLC => I/O emulated or performed | ||
| 548 | ; | ||
| 549 | ;------------------------------------------------------------------------------ | ||
| 550 | |||
| 551 | DMACnt0to7 proc near | ||
| 552 | |||
| 553 | DMACnt4: ; I/O port C2h | ||
| 554 | DMACnt5: ; I/O port C6h | ||
| 555 | DMACnt6: ; I/O port CAh | ||
| 556 | DMACnt7: ; I/O port CEh | ||
| 557 | push ax | ||
| 558 | push bx | ||
| 559 | push cx | ||
| 560 | push dx | ||
| 561 | push si | ||
| 562 | ; | ||
| 563 | ; Now, BX = port * 2 and DX = IO code | ||
| 564 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 565 | ; | ||
| 566 | xchg dx, bx | ||
| 567 | shr dx, 1 | ||
| 568 | xchg bh,bl ; move IO code to bh | ||
| 569 | |||
| 570 | mov si, dx | ||
| 571 | sub si, 0B2h ; SI = 4 * channel # | ||
| 572 | shl si, 2 ; si = 16 * channel # | ||
| 573 | mov bl, [DMARegSav.DMAFF2] ; get flip-flop | ||
| 574 | xor [DMARegSav.DMAFF2], 1 ; toggle our flip-flop | ||
| 575 | jmp short DMACntN | ||
| 576 | |||
| 577 | DMACnt0: ; I/O port 01h | ||
| 578 | DMACnt1: ; I/O port 03h | ||
| 579 | DMACnt2: ; I/O port 05h | ||
| 580 | DMACnt3: ; I/O port 07h | ||
| 581 | push ax | ||
| 582 | push bx | ||
| 583 | push cx | ||
| 584 | push dx | ||
| 585 | push si | ||
| 586 | ; | ||
| 587 | ; Now, BX = port * 2 and DX = IO code | ||
| 588 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 589 | ; | ||
| 590 | xchg dx, bx | ||
| 591 | shr dx, 1 | ||
| 592 | xchg bh,bl ; move IO code to bh | ||
| 593 | |||
| 594 | mov si, dx | ||
| 595 | dec si | ||
| 596 | shl si, 3 ; si = 16 * channel # | ||
| 597 | mov bl, [DMARegSav.DMAFF1] ; get flip-flop | ||
| 598 | xor [DMARegSav.DMAFF1], 1 ; toggle our flip-flop | ||
| 599 | ; | ||
| 600 | ; FALL THROUGH!!! | ||
| 601 | ; | ||
| 602 | |||
| 603 | ;****************************************************************************** | ||
| 604 | ; | ||
| 605 | ; DMACntN - Write/Read DMA Channel N Count Register | ||
| 606 | ; | ||
| 607 | ; ENTRY: As DMACnt1to7 plus | ||
| 608 | ; si = 16 * channel # | ||
| 609 | ; | ||
| 610 | ;------------------------------------------------------------------------------ | ||
| 611 | DMACntN: | ||
| 612 | and bl, 1 ; Look at bit0 only - Safety | ||
| 613 | |||
| 614 | or bh,bh ;Q: Input ? | ||
| 615 | jz short DMA_CntN_rd ; Y: do Read operation | ||
| 616 | ; N: save value "written" | ||
| 617 | mov [SaveAL], al ; save AL in Save area. | ||
| 618 | xor bh, bh ; make BX = Flip Flop state | ||
| 619 | mov byte ptr DMARegSav.DMACount[bx][si], al ; save cnt | ||
| 620 | out dx, al ; do the I/O | ||
| 621 | |||
| 622 | xor bl,1 ; Toggle flip-flop for Wrt | ||
| 623 | call DMA_DMAFixup ; Translate Lin to Phys | ||
| 624 | ; & Update DMARegSav | ||
| 625 | call DMA_WrtAdrReg ; emulate the write | ||
| 626 | call DMALoadCount | ||
| 627 | |||
| 628 | jmp short DCExit | ||
| 629 | DMA_CntN_rd: | ||
| 630 | xor bh,bh ; make BX = Flip Flop state | ||
| 631 | in al, dx ; Toggle the real flip-flop | ||
| 632 | ; to match bx above | ||
| 633 | mov [SaveAL], al | ||
| 634 | |||
| 635 | jmp $+2 | ||
| 636 | jmp $+2 | ||
| 637 | xor bl,1 ; and the s/w one | ||
| 638 | ; | ||
| 639 | ; get current count values from cntlr | ||
| 640 | ; | ||
| 641 | in al, dx ; get 2nd byte of Count reg | ||
| 642 | jmp $+2 ; timing ... | ||
| 643 | jmp $+2 ; timing ... | ||
| 644 | mov byte ptr DMARegSav.DMACount[bx][si], al ; save it | ||
| 645 | xor bl, 1 ; flip to other byte | ||
| 646 | in al, dx ; get 1st byte of Count reg | ||
| 647 | mov byte ptr DMARegSav.DMACount[bx][si], al ; save it | ||
| 648 | DCExit: | ||
| 649 | pop si | ||
| 650 | pop dx | ||
| 651 | pop cx | ||
| 652 | pop bx | ||
| 653 | pop ax | ||
| 654 | mov al, [SaveAL] | ||
| 655 | |||
| 656 | clc ; I/O emulated, return | ||
| 657 | ret | ||
| 658 | |||
| 659 | DMACnt0to7 endp | ||
| 660 | |||
| 661 | page | ||
| 662 | ;****************************************************************************** | ||
| 663 | ; | ||
| 664 | ; DMAPgN - Write/Read DMA Channel N Page Register | ||
| 665 | ; | ||
| 666 | ; ENTRY: | ||
| 667 | ; AL = byte to output to port | ||
| 668 | ; BX = port * 2 | ||
| 669 | ; DX = 0 => Emulate Input | ||
| 670 | ; <>0 => Emulate Output | ||
| 671 | ; si = 2 * Channel # | ||
| 672 | ; | ||
| 673 | ; EXIT: | ||
| 674 | ; AL = emulated input/output value from port. | ||
| 675 | ; CLC => I/O emulated or performed | ||
| 676 | ; | ||
| 677 | ; USED: EBX,Flags | ||
| 678 | ; STACK: | ||
| 679 | ; | ||
| 680 | ; NOTES: For channels 0-4, DMACount is in Bytes, and | ||
| 681 | ; DMALinAdr holds the address as: | ||
| 682 | ; | ||
| 683 | ; +-----------+-----------+----------------------+ | ||
| 684 | ; | 31-24 | 23-16 | 15-0 | | ||
| 685 | ; +-----------+-----------+----------------------+ | ||
| 686 | ; | 0000 0000 | A23-A16 | A15-A0 | | ||
| 687 | ; +-----------+-----------+----------------------+ | ||
| 688 | ; | ||
| 689 | ; For channels 5-7, DMACount is in Words, and | ||
| 690 | ; DMALinAdr holds the address as: | ||
| 691 | ; | ||
| 692 | ; +-----------+-----------+----------------------+ | ||
| 693 | ; | 31-24 |23-17 | 16 | 15-0 | | ||
| 694 | ; +-----------+-----------+----------------------+ | ||
| 695 | ; | 0000 0000 |A23-A17 |0 | A16-A1 | | ||
| 696 | ; +-----------+-----------+----------------------+ | ||
| 697 | ; | ||
| 698 | ; | ||
| 699 | ;------------------------------------------------------------------------------ | ||
| 700 | DMAPg0to7 proc near | ||
| 701 | |||
| 702 | DMAPg0: | ||
| 703 | push si | ||
| 704 | mov si,0*16 ; si = 16 * channel # | ||
| 705 | jmp short DMAPgN | ||
| 706 | DMAPg1: | ||
| 707 | push si | ||
| 708 | mov si,1*16 ; si = 16 * channel # | ||
| 709 | jmp short DMAPgN | ||
| 710 | DMAPg2: | ||
| 711 | push si | ||
| 712 | mov si,2*16 ; si = 16 * channel # | ||
| 713 | jmp short DMAPgN | ||
| 714 | DMAPg3: | ||
| 715 | push si | ||
| 716 | mov si,3*16 ; si = 16 * channel # | ||
| 717 | jmp short DMAPgN | ||
| 718 | DMAPg5: | ||
| 719 | push si | ||
| 720 | mov si,5*16 ; si = 16 * channel # | ||
| 721 | jmp short DMAPgN | ||
| 722 | DMAPg6: | ||
| 723 | push si | ||
| 724 | mov si,6*16 ; si = 16 * channel # | ||
| 725 | jmp short DMAPgN | ||
| 726 | DMAPg7: | ||
| 727 | push si | ||
| 728 | mov si,7*16 ; si = 16 * channel # | ||
| 729 | ; FALL THROUGH | ||
| 730 | |||
| 731 | ;---------------------------------------------------------------------- | ||
| 732 | ; DMAPgN - Common Page Code | ||
| 733 | ; | ||
| 734 | ; ENTRY: As above plus | ||
| 735 | ; si = 16 * Channel # | ||
| 736 | ; | ||
| 737 | ;---------------------------------------------------------------------- | ||
| 738 | |||
| 739 | DMAPgN: | ||
| 740 | push ax | ||
| 741 | push bx | ||
| 742 | push cx | ||
| 743 | push dx | ||
| 744 | ; | ||
| 745 | ; Now, BX = port * 2 and DX = IO code | ||
| 746 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 747 | ; | ||
| 748 | xchg dx, bx | ||
| 749 | shr dx, 1 | ||
| 750 | xchg bh,bl ; move IO code to bh | ||
| 751 | |||
| 752 | or bh,bh ;Q: Input ? | ||
| 753 | jz short Pg_rd_port ; Y: do Read operation | ||
| 754 | |||
| 755 | mov [SaveAL], al ; save AL in Save area. | ||
| 756 | ; | ||
| 757 | ; Get s/w FF for WrtAdrReg | ||
| 758 | ; | ||
| 759 | mov bl, [DMARegSav.DMAFF1] ; Assume Chan 1 FF | ||
| 760 | cmp si, 4*16 ; Q: Addr for 2nd controller | ||
| 761 | jb short PgN_FF ; A: No, FF is correct | ||
| 762 | mov bl, [DMARegSav.DMAFF2] ; Chan 2 FF | ||
| 763 | PgN_FF: | ||
| 764 | xor bh, bh ; make BX = flip-flop state | ||
| 765 | |||
| 766 | mov byte ptr DMARegSav.DMALinAdr.HighWord[si], al ; save value | ||
| 767 | call DMA_DMAFixup ; Translate Lin to Phys | ||
| 768 | ; & Update DMARegSav | ||
| 769 | call DMA_WrtAdrReg ; emulate the write | ||
| 770 | jmp short DPExit | ||
| 771 | Pg_rd_port: | ||
| 772 | mov al, byte ptr DMARegSav.DMALinAdr.HighWord[si] | ||
| 773 | mov [SaveAL], al | ||
| 774 | DPExit: | ||
| 775 | pop dx | ||
| 776 | pop cx | ||
| 777 | pop bx | ||
| 778 | pop ax | ||
| 779 | pop si | ||
| 780 | mov al, [SaveAL] | ||
| 781 | clc | ||
| 782 | ret | ||
| 783 | |||
| 784 | DMAPg0to7 endp | ||
| 785 | |||
| 786 | page | ||
| 787 | |||
| 788 | ;****************************************************************************** | ||
| 789 | ; | ||
| 790 | ; DMAClrFF1 - Reset Controller 1's FlipFlop | ||
| 791 | ; DMAClrFF2 - Reset Controller 2's FlipFlop | ||
| 792 | ; | ||
| 793 | ; ENTRY: | ||
| 794 | ; AL = byte to output to port. | ||
| 795 | ; BX = port * 2 | ||
| 796 | ; DH = 0 => Emulate Input. | ||
| 797 | ; <>0 => Emulate Output. | ||
| 798 | ; | ||
| 799 | ; EXIT: | ||
| 800 | ; AL = emulated input/output value from port. | ||
| 801 | ; CLC => I/O emulated or performed | ||
| 802 | ; | ||
| 803 | ;------------------------------------------------------------------------------ | ||
| 804 | |||
| 805 | DMAClrFF1 proc near | ||
| 806 | push ax | ||
| 807 | push bx | ||
| 808 | push cx | ||
| 809 | push dx | ||
| 810 | ; | ||
| 811 | ; Now, BX = port * 2 and DX = IO code | ||
| 812 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 813 | ; | ||
| 814 | xchg bx, dx | ||
| 815 | shr dx, 1 | ||
| 816 | xchg bh,bl ; move IO code to bh | ||
| 817 | |||
| 818 | or bh,bh ;Q: Input ? | ||
| 819 | jz short DMA_CLF_RdEm ; Y: Let it go | ||
| 820 | out dx, al ; N: do it | ||
| 821 | mov [DMARegSav.DMAFF1], 0 | ||
| 822 | jmp short DMACFFexit | ||
| 823 | DMA_CLF_RdEm: | ||
| 824 | in al,dx ; do the read | ||
| 825 | DMACFFexit: | ||
| 826 | pop dx | ||
| 827 | pop cx | ||
| 828 | pop bx | ||
| 829 | pop ax | ||
| 830 | clc | ||
| 831 | ret | ||
| 832 | |||
| 833 | DMAClrFF1 endp | ||
| 834 | |||
| 835 | DMAClrFF2 proc near | ||
| 836 | |||
| 837 | push ax | ||
| 838 | push bx | ||
| 839 | push cx | ||
| 840 | push dx | ||
| 841 | ; | ||
| 842 | ; Now, BX = port * 2 and DX = IO code | ||
| 843 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 844 | ; | ||
| 845 | xchg bx, dx | ||
| 846 | shr dx, 1 | ||
| 847 | xchg bh,bl ; move IO code to bh | ||
| 848 | |||
| 849 | or bh,bh ;Q: Input ? | ||
| 850 | jz DMA_CLF_RdEm ; Y: Let it go | ||
| 851 | out dx, al ; N: do it | ||
| 852 | mov [DMARegSav.DMAFF2], 0 | ||
| 853 | jmp DMACFFexit | ||
| 854 | |||
| 855 | DMAClrFF2 endp | ||
| 856 | |||
| 857 | page | ||
| 858 | ;****************************************************************************** | ||
| 859 | ; | ||
| 860 | ; DMAMode1 - Track Controller 1's Mode Register | ||
| 861 | ; DMAMode2 - Track Controller 2's Mode Register | ||
| 862 | ; | ||
| 863 | ; ENTRY: | ||
| 864 | ; AL = byte to output to port. | ||
| 865 | ; BX = port * 2 | ||
| 866 | ; DX = 0 => Emulate Input. | ||
| 867 | ; <>0 => Emulate Output. | ||
| 868 | ; | ||
| 869 | ; EXIT: | ||
| 870 | ; AL = emulated input/output value from port. | ||
| 871 | ; CLC => I/O emulated or performed | ||
| 872 | ; | ||
| 873 | ;------------------------------------------------------------------------------ | ||
| 874 | |||
| 875 | DMAMode1 proc near | ||
| 876 | push ax | ||
| 877 | push bx | ||
| 878 | push cx | ||
| 879 | push dx | ||
| 880 | push si | ||
| 881 | ; | ||
| 882 | ; Now, BX = port * 2 and DX = IO code | ||
| 883 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 884 | ; | ||
| 885 | xchg bx, dx | ||
| 886 | shr dx, 1 | ||
| 887 | xchg bh,bl ; move IO code to bh | ||
| 888 | |||
| 889 | or bh,bh ;Q: Input ? | ||
| 890 | jz short DMA_Mread ; Y: Let it go | ||
| 891 | |||
| 892 | mov [SaveAL], al ; save AL in Save area. | ||
| 893 | xor ah, ah | ||
| 894 | mov si, ax | ||
| 895 | and si, DMA_M_CHANNEL | ||
| 896 | mov bl, al | ||
| 897 | and bl, NOT DMA_M_16BIT ; 8 bit xfers for controller 1 | ||
| 898 | DMA_Mboth: | ||
| 899 | shl si, 4 ; Channel * 16 | ||
| 900 | mov [DMARegSav.DMAMode][si], bl | ||
| 901 | out dx, al ; N: do it | ||
| 902 | jmp short DMExit | ||
| 903 | |||
| 904 | DMA_Mread: | ||
| 905 | in al, dx ; do the read | ||
| 906 | mov [SaveAL], al | ||
| 907 | DMExit: | ||
| 908 | pop si | ||
| 909 | pop dx | ||
| 910 | pop cx | ||
| 911 | pop bx | ||
| 912 | pop ax | ||
| 913 | mov al, [SaveAL] | ||
| 914 | clc | ||
| 915 | ret | ||
| 916 | DMAMode1 endp | ||
| 917 | |||
| 918 | DMAMode2 proc near | ||
| 919 | |||
| 920 | push ax | ||
| 921 | push bx | ||
| 922 | push cx | ||
| 923 | push dx | ||
| 924 | push si | ||
| 925 | ; | ||
| 926 | ; Now, BX = port * 2 and DX = IO code | ||
| 927 | ; Code ported from Win/386 expects DX = port and BH = IO code | ||
| 928 | ; | ||
| 929 | xchg bx, dx | ||
| 930 | shr dx, 1 | ||
| 931 | xchg bh,bl ; move IO code to bh | ||
| 932 | |||
| 933 | or bh,bh ;Q: Input ? | ||
| 934 | jz DMA_Mread ; Y: Let it go | ||
| 935 | |||
| 936 | mov [SaveAL], al ; save AL in Save area. | ||
| 937 | xor ah, ah | ||
| 938 | mov si, ax | ||
| 939 | and si, DMA_M_CHANNEL | ||
| 940 | add si, 4 ; Channel 4 to 7 | ||
| 941 | mov bl, al | ||
| 942 | or bl, DMA_M_16BIT ; 16 bit for controller 2 | ||
| 943 | jmp DMA_Mboth | ||
| 944 | |||
| 945 | DMAMode2 endp | ||
| 946 | |||
| 947 | ; INCLUDE VDMAD2.ASM | ||
| 948 | |||
| 949 | page | ||
| 950 | ;****************************************************************************** | ||
| 951 | ;DMA_GetLinAdr - return Linear Address, count and mode from DMARegSave area | ||
| 952 | ; | ||
| 953 | ; ENTRY: | ||
| 954 | ; si = channel # * 16 | ||
| 955 | ; DS assume DGROUP | ||
| 956 | ; | ||
| 957 | ; EXIT: | ||
| 958 | ; EAX = linear Base Address | ||
| 959 | ; ECX = SIZE of transfer (bytes) | ||
| 960 | ; DL = Mode register | ||
| 961 | ; | ||
| 962 | ; USED: Flags | ||
| 963 | ; STACK: | ||
| 964 | ;------------------------------------------------------------------------------ | ||
| 965 | DMA_GetLinAdr proc near | ||
| 966 | |||
| 967 | mov eax, dword ptr DMARegSav.DMALinAdr[si] | ||
| 968 | mov ecx, dword ptr DMARegSav.DMACount[si] | ||
| 969 | mov dl, byte ptr DMARegSav.DMAMode[si] | ||
| 970 | inc ecx ; ECX = SIZE of transfer | ||
| 971 | test dl, DMA_M_16BIT ; Word transfer? | ||
| 972 | jz short GLexit ; N: no special treatment | ||
| 973 | |||
| 974 | DMA_WADDR_TO_BADDR ; Y: fixup values from regs | ||
| 975 | GLexit: | ||
| 976 | ret | ||
| 977 | |||
| 978 | DMA_GetLinAdr endp | ||
| 979 | |||
| 980 | page | ||
| 981 | ;****************************************************************************** | ||
| 982 | ; DMA_SetPhyAdr - Load the Page and Base DMA registers with the input | ||
| 983 | ; Physical Address and save this addr as current phy addr. | ||
| 984 | ; | ||
| 985 | ; ENTRY: | ||
| 986 | ; EAX = physical address | ||
| 987 | ; SI = DMA channel # * 16 | ||
| 988 | ; DS -> DGROUP | ||
| 989 | ; | ||
| 990 | ; USED: Flags | ||
| 991 | ;------------------------------------------------------------------------------ | ||
| 992 | DMA_SetPhyAdr proc near | ||
| 993 | ; | ||
| 994 | push eax | ||
| 995 | push bx | ||
| 996 | push dx | ||
| 997 | |||
| 998 | xor bh, bh | ||
| 999 | mov bl, [DMARegSav.DMAFF1] | ||
| 1000 | cmp si,4*16 ; 2nd cntlr? | ||
| 1001 | jb short DMA_SPA1 | ||
| 1002 | mov bl, [DMARegSav.DMAFF2] ; yes, other flip-flop | ||
| 1003 | DMA_SPA1: | ||
| 1004 | test [DMARegSav.DMAMode][si], DMA_M_16BIT ; word transfer? | ||
| 1005 | jz short SaveIt ; no, no translation | ||
| 1006 | DMA_BADDR_TO_WADDR | ||
| 1007 | SaveIt: | ||
| 1008 | mov dword ptr DMARegSav.DMAPhyAdr[si], eax | ||
| 1009 | |||
| 1010 | ; set page register | ||
| 1011 | xor dh, dh | ||
| 1012 | mov dl, byte ptr DMARegSav.DMAPagePort[si] | ||
| 1013 | mov al, byte ptr DMARegSav.DMAPhyAdr.HighWord[si] | ||
| 1014 | out dx, al | ||
| 1015 | |||
| 1016 | ; set base address register | ||
| 1017 | mov dl, byte ptr DMARegSav.DMABasePort[si] | ||
| 1018 | mov al, byte ptr DMARegSav.DMAPhyAdr[si][bx] | ||
| 1019 | out dx,al ; send out 1st byte | ||
| 1020 | xor bl,1 ; toggle FF | ||
| 1021 | jmp $+2 | ||
| 1022 | jmp $+2 | ||
| 1023 | mov al, byte ptr DMARegSav.DMAPhyAdr[si][bx] | ||
| 1024 | out dx,al ; send out other byte | ||
| 1025 | xor bl,1 ; toggle FF to original state | ||
| 1026 | |||
| 1027 | pop dx | ||
| 1028 | pop bx | ||
| 1029 | pop eax | ||
| 1030 | ret | ||
| 1031 | ; | ||
| 1032 | DMA_SetPhyAdr endp | ||
| 1033 | |||
| 1034 | page | ||
| 1035 | ;****************************************************************************** | ||
| 1036 | ; DMALoadCount - Load the Count DMA register with the input | ||
| 1037 | ; | ||
| 1038 | ; ENTRY: | ||
| 1039 | ; si = DMA channel # * 16 | ||
| 1040 | ; | ||
| 1041 | ;------------------------------------------------------------------------------ | ||
| 1042 | DMALoadCount proc near | ||
| 1043 | push bx | ||
| 1044 | push ax | ||
| 1045 | push dx | ||
| 1046 | |||
| 1047 | xor bh, bh | ||
| 1048 | mov bl, byte ptr [DMARegSav.DMAFF1] | ||
| 1049 | cmp si,4*16 ;Q: Adrs from 2nd cntlr | ||
| 1050 | jb short DMA_SC1 ; N: save it as is | ||
| 1051 | mov bl, byte ptr [DMARegSav.DMAFF2] | ||
| 1052 | |||
| 1053 | DMA_SC1: | ||
| 1054 | mov dl, byte ptr DMARegSav.DMACntPort[si] | ||
| 1055 | xor dh, dh | ||
| 1056 | mov al, byte ptr DMARegSav.DMACount[bx][si] | ||
| 1057 | out dx, al | ||
| 1058 | jmp $+2 | ||
| 1059 | jmp $+2 | ||
| 1060 | xor bl, 1 | ||
| 1061 | mov al, byte ptr DMARegSav.DMACount[bx][si] | ||
| 1062 | out dx, al | ||
| 1063 | |||
| 1064 | pop dx | ||
| 1065 | pop ax | ||
| 1066 | pop bx | ||
| 1067 | ret | ||
| 1068 | |||
| 1069 | DMALoadCount endp | ||
| 1070 | |||
| 1071 | page | ||
| 1072 | ;****************************************************************************** | ||
| 1073 | ; DMA_DMAFixup - Fixup Linear to Physical mapping for DMA | ||
| 1074 | ; | ||
| 1075 | ; ENTRY: | ||
| 1076 | ; SI = 16 * channel # | ||
| 1077 | ; DS assume DGROUP | ||
| 1078 | ; | ||
| 1079 | ; EXIT: | ||
| 1080 | ; DMARegSav is updated | ||
| 1081 | ; | ||
| 1082 | ; USED: flags, registers (calls a C program, so most registers are trashed) | ||
| 1083 | ; | ||
| 1084 | ; Check to see if DMA Page fixup is needed. | ||
| 1085 | ; We test for the following cases for optimization: | ||
| 1086 | ; Lin Base Add == Lin Page Reg == 0, assume that transfer addr | ||
| 1087 | ; is not yet valid | ||
| 1088 | ; | ||
| 1089 | ;------------------------------------------------------------------------------ | ||
| 1090 | DMA_DMAFixup proc near | ||
| 1091 | ;Q: LinAddr = 0? | ||
| 1092 | |||
| 1093 | mov eax, dword ptr DMARegSav.DMALinAdr[si] | ||
| 1094 | or eax,eax | ||
| 1095 | jz short DMA_nofixup ; Y:DMA not programmed yet | ||
| 1096 | ;Do the fixup..... | ||
| 1097 | pushfd ; ENABLE INTERRUPTS! | ||
| 1098 | push bx ; C code trashes these regs | ||
| 1099 | push es | ||
| 1100 | ; | ||
| 1101 | ; long SwapDMAPages(LinAdr, Len, XferSize); | ||
| 1102 | ; long LinAdr, Len; | ||
| 1103 | ; unsigned XferSize; 0/1 Byte/word Xfer | ||
| 1104 | ; | ||
| 1105 | movzx eax, [DMARegSav.DMAMode][si] | ||
| 1106 | and al, DMA_M_16BIT ; Non-zero for 16bit transfer | ||
| 1107 | push ax ; push XferSize | ||
| 1108 | |||
| 1109 | call DMA_GetLinAdr | ||
| 1110 | push ecx ; push count | ||
| 1111 | push eax ; push LinAdr | ||
| 1112 | ; | ||
| 1113 | ; C code saves di si bp ds ss sp | ||
| 1114 | |||
| 1115 | call _SwapDMAPages ; C program to do the dirty work | ||
| 1116 | |||
| 1117 | xchg ax, dx | ||
| 1118 | shl eax, 16 | ||
| 1119 | mov ax, dx ; eax = returned value | ||
| 1120 | |||
| 1121 | add sp, 10 ; clean up stack | ||
| 1122 | |||
| 1123 | pop es | ||
| 1124 | pop bx | ||
| 1125 | popfd ; Restore original FLAGS state | ||
| 1126 | |||
| 1127 | test [DMARegSav.DMAMode][si], DMA_M_16BIT ; word transfer? | ||
| 1128 | jz short SavIt ; no, no translation | ||
| 1129 | DMA_BADDR_TO_WADDR ; Y: Put in special format | ||
| 1130 | SavIt: | ||
| 1131 | mov dword ptr DMARegSav.DMAPhyAdr[si], eax | ||
| 1132 | clc ; Done fixup | ||
| 1133 | ret | ||
| 1134 | DMA_nofixup: | ||
| 1135 | stc | ||
| 1136 | ret | ||
| 1137 | |||
| 1138 | DMA_DMAFixup endp | ||
| 1139 | |||
| 1140 | page | ||
| 1141 | ;****************************************************************************** | ||
| 1142 | ; DMA_WrtAdrReg - Write registers associated with DMA address | ||
| 1143 | ; | ||
| 1144 | ; ENTRY: | ||
| 1145 | ; BX = Flip Flop State, 0 or 1 | ||
| 1146 | ; SI = channel # * 16 | ||
| 1147 | ; DS assume DGROUP | ||
| 1148 | ; Uses Values in DMARegSav | ||
| 1149 | ; | ||
| 1150 | ; EXIT: | ||
| 1151 | ; | ||
| 1152 | ; USED: Flags, EAX | ||
| 1153 | ; STACK: | ||
| 1154 | ;------------------------------------------------------------------------------ | ||
| 1155 | DMA_WrtAdrReg proc near | ||
| 1156 | |||
| 1157 | ; Must Update Page and Base registers simultaneously when remapping occurs... | ||
| 1158 | push bx | ||
| 1159 | push dx | ||
| 1160 | |||
| 1161 | and bx, 1 ; Lose extra bit just in case... | ||
| 1162 | ; Base Register... | ||
| 1163 | xor dh, dh ; clear high byte | ||
| 1164 | |||
| 1165 | ; NOTE: Internal flip- | ||
| 1166 | ; flop flag not updated, | ||
| 1167 | ; since we write twice.... | ||
| 1168 | ; BX = flip flop state | ||
| 1169 | |||
| 1170 | mov dl, byte ptr DMARegSav.DMABasePort[si] | ||
| 1171 | mov al, byte ptr DMARegSav.DMAPhyAdr[bx][si] | ||
| 1172 | out dx, al ; output the byte | ||
| 1173 | jmp $+2 ; timing | ||
| 1174 | jmp $+2 ; timing | ||
| 1175 | xor bx, 1 ; toggle flip-flop | ||
| 1176 | |||
| 1177 | mov al, byte ptr DMARegSav.DMAPhyAdr[bx][si] | ||
| 1178 | out dx, al ; output the byte | ||
| 1179 | jmp $+2 ; timing | ||
| 1180 | jmp $+2 ; timing | ||
| 1181 | xor bx, 1 ; toggle flip-flop | ||
| 1182 | |||
| 1183 | ; Page Register... | ||
| 1184 | mov al, byte ptr DMARegSav.DMAPhyAdr.HighWord[si] ; fetch value | ||
| 1185 | mov dl, byte ptr DMARegSav.DMAPagePort[si] | ||
| 1186 | out dx,al ; output the byte | ||
| 1187 | |||
| 1188 | pop dx | ||
| 1189 | pop bx | ||
| 1190 | ret | ||
| 1191 | |||
| 1192 | DMA_WrtAdrReg endp | ||
| 1193 | |||
| 1194 | page | ||
| 1195 | ;****************************************************************************** | ||
| 1196 | ; InitELIM - initialize LIM h/w trapping data structures and | ||
| 1197 | ; I/O bit map for this ports. | ||
| 1198 | ; | ||
| 1199 | ; NOTE: this is a FAR routine | ||
| 1200 | ; | ||
| 1201 | ; ENTRY: Real Mode | ||
| 1202 | ; | ||
| 1203 | ; EXIT: Real Mode | ||
| 1204 | ; TSS:[IOBitMap] - LIM addresses entered in I/O bit map | ||
| 1205 | ; | ||
| 1206 | ; USED: Flags | ||
| 1207 | ; STACK: | ||
| 1208 | ;------------------------------------------------------------------------------ | ||
| 1209 | InitELIM proc far | ||
| 1210 | |||
| 1211 | push ax | ||
| 1212 | push bx | ||
| 1213 | push cx | ||
| 1214 | push si | ||
| 1215 | push di | ||
| 1216 | push ds | ||
| 1217 | push es | ||
| 1218 | |||
| 1219 | cld | ||
| 1220 | |||
| 1221 | mov ax,seg DGROUP | ||
| 1222 | mov ds,ax | ||
| 1223 | ; | ||
| 1224 | ; now set entries in I/O Bit Map | ||
| 1225 | ; | ||
| 1226 | mov ax,TSS | ||
| 1227 | mov es,ax ; ES -> TSS | ||
| 1228 | ; | ||
| 1229 | ; now set DMA ports in I/O Bit Map | ||
| 1230 | ; | ||
| 1231 | mov cx,LIMDMAP_CNT | ||
| 1232 | mov si,offset DGROUP:DMAP_Page ; DS:SI -> DMA ports | ||
| 1233 | mov bx,8000h ; trap it every 1k | ||
| 1234 | IE_maploop: | ||
| 1235 | lodsw ; AX = port to trap | ||
| 1236 | call PortTrap ; set bit(s) for this port | ||
| 1237 | loop IE_maploop ;if more ... | ||
| 1238 | |||
| 1239 | pop es | ||
| 1240 | pop ds | ||
| 1241 | pop di | ||
| 1242 | pop si | ||
| 1243 | pop cx | ||
| 1244 | pop bx | ||
| 1245 | pop ax | ||
| 1246 | ret | ||
| 1247 | |||
| 1248 | InitELIM endp | ||
| 1249 | |||
| 1250 | |||
| 1251 | ; | ||
| 1252 | ; C callable routines for manipulating page table entries. | ||
| 1253 | ; and Current FRS - CurRegSet | ||
| 1254 | |||
| 1255 | |||
| 1256 | ; | ||
| 1257 | ; Equates for picking up arguments passed in from C code. | ||
| 1258 | ; Arg1 - word Arg, | ||
| 1259 | ; Arg2 - word or dword Arg | ||
| 1260 | ; | ||
| 1261 | |||
| 1262 | Arg1 equ [BP+4] | ||
| 1263 | Arg2 equ [BP+6] | ||
| 1264 | |||
| 1265 | |||
| 1266 | ;***************************************************************************** | ||
| 1267 | ; | ||
| 1268 | ; _GetPte - called from C code | ||
| 1269 | ; | ||
| 1270 | ; return pte in dx:ax | ||
| 1271 | ; | ||
| 1272 | ; long GetPte(PTIndex) | ||
| 1273 | ; unsigned PTIndex; | ||
| 1274 | ; | ||
| 1275 | ; Written: JHB Aug 10,1988 | ||
| 1276 | ; Modif: ISP Aug 12,1988 parameter should be returned in dx:ax not eax | ||
| 1277 | ; removed some of pushes and pops | ||
| 1278 | ; added cld before load just to be safe | ||
| 1279 | ; offset specified in DGROUP | ||
| 1280 | ; | ||
| 1281 | ; JHB Aug 21 88 changed input param to PTIndex | ||
| 1282 | ; | ||
| 1283 | ;***************************************************************************** | ||
| 1284 | |||
| 1285 | _GetPte proc near | ||
| 1286 | |||
| 1287 | push bp | ||
| 1288 | mov bp, sp | ||
| 1289 | push si | ||
| 1290 | push ds | ||
| 1291 | |||
| 1292 | mov ax, PAGET_GSEL | ||
| 1293 | mov ds, ax | ||
| 1294 | |||
| 1295 | mov si, WORD PTR Arg1 | ||
| 1296 | shl si, 2 ; dword entries in the PT | ||
| 1297 | |||
| 1298 | cld | ||
| 1299 | lodsw ; get low word | ||
| 1300 | mov dx, ax ; into dx | ||
| 1301 | lodsw ; get hiword | ||
| 1302 | xchg dx, ax ; dx:ax = long return value | ||
| 1303 | |||
| 1304 | pop ds | ||
| 1305 | pop si | ||
| 1306 | pop bp | ||
| 1307 | ret | ||
| 1308 | _GetPte endp | ||
| 1309 | |||
| 1310 | ;***************************************************************************** | ||
| 1311 | ; | ||
| 1312 | ; _SetPte - called from C code | ||
| 1313 | ; | ||
| 1314 | ; Locate the PT entry for given EmmPhyPage and set it to pte. | ||
| 1315 | ; | ||
| 1316 | ; SetPte(PTIndex, pte) | ||
| 1317 | ; unsigned PTIndex; | ||
| 1318 | ; long pte; | ||
| 1319 | ; | ||
| 1320 | ; WRITTEN: JHB Aug 10,1988 | ||
| 1321 | ; MODIF: ISP Aug 12,1988 pushes and pops removed | ||
| 1322 | ; cld added for safety | ||
| 1323 | ; offset specified in DGROUP | ||
| 1324 | ; pushed poped eax (check on this) | ||
| 1325 | ; | ||
| 1326 | ; JHB Aug 21, 1988 changed first input param to PTIndex | ||
| 1327 | ; | ||
| 1328 | ;***************************************************************************** | ||
| 1329 | |||
| 1330 | |||
| 1331 | _SetPte proc near | ||
| 1332 | |||
| 1333 | push bp | ||
| 1334 | mov bp, sp | ||
| 1335 | push di | ||
| 1336 | push es | ||
| 1337 | |||
| 1338 | mov ax, PAGET_GSEL | ||
| 1339 | mov es, ax | ||
| 1340 | mov di, WORD PTR Arg1 | ||
| 1341 | shl di, 2 | ||
| 1342 | |||
| 1343 | mov eax, DWORD PTR Arg2 | ||
| 1344 | and ax, 0F000H ; clear low 12 bits | ||
| 1345 | or ax, P_AVAIL ; page control bits - user, present, write | ||
| 1346 | |||
| 1347 | cld | ||
| 1348 | stosd | ||
| 1349 | ; | ||
| 1350 | ; reload CR3 to flush TLB | ||
| 1351 | ; | ||
| 1352 | mov eax, CR3 | ||
| 1353 | mov CR3, eax | ||
| 1354 | |||
| 1355 | ; mov eax,dword ptr [Page_Dir] ; mov EAX,dword ptr [Page_Dir] | ||
| 1356 | ; db 0Fh,22h,18h ; mov CR3,EAX | ||
| 1357 | |||
| 1358 | pop es | ||
| 1359 | pop di | ||
| 1360 | pop bp | ||
| 1361 | ret | ||
| 1362 | _SetPte endp | ||
| 1363 | |||
| 1364 | ;***************************************************************************** | ||
| 1365 | ; | ||
| 1366 | ; _GetCRSEntry - called from C code | ||
| 1367 | ; | ||
| 1368 | ; return the Emm page mapped to the EmmPhyPage by looking up CurRegSet. | ||
| 1369 | ; | ||
| 1370 | ; unsigned GetCRSEntry(EmmPhyPage) | ||
| 1371 | ; unsigned EmmPhyPage | ||
| 1372 | ; | ||
| 1373 | ; WRITTEN: JHB Aug 10,1988 | ||
| 1374 | ; MODIF: ISP Aug 12,1988 pushes and pops removed | ||
| 1375 | ; Offset specified in DGROUP | ||
| 1376 | ; cld added for safety | ||
| 1377 | ;***************************************************************************** | ||
| 1378 | |||
| 1379 | _GetCRSEntry proc near | ||
| 1380 | |||
| 1381 | push bp | ||
| 1382 | mov bp, sp | ||
| 1383 | push di | ||
| 1384 | |||
| 1385 | mov bx, WORD PTR Arg1 | ||
| 1386 | shl bx, 1 ; each FRS entry is a word | ||
| 1387 | Get_FRS_Window DI ; di = address of Current FRS | ||
| 1388 | add di, bx | ||
| 1389 | mov ax, word ptr [di] ; load FRS entry | ||
| 1390 | |||
| 1391 | pop di | ||
| 1392 | pop bp | ||
| 1393 | ret | ||
| 1394 | _GetCRSEntry endp | ||
| 1395 | |||
| 1396 | ; | ||
| 1397 | ; Equates for picking up long Arguments from C code | ||
| 1398 | ; LArg1 - long Arg | ||
| 1399 | ; Larg2 - long Arg when the first Arg is also long | ||
| 1400 | ; | ||
| 1401 | |||
| 1402 | LArg1 equ [BP+4] | ||
| 1403 | LArg2 equ [BP+8] | ||
| 1404 | |||
| 1405 | ;***************************************************************************** | ||
| 1406 | ; | ||
| 1407 | ; _GetDMALinAdr - called from C code | ||
| 1408 | ; | ||
| 1409 | ; returns the Lin Adr for the DMA buffer whose physical adr is given | ||
| 1410 | ; | ||
| 1411 | ; long GetDMALinAdr(DMAPhyAdr) | ||
| 1412 | ; long DMAPhyAdr; | ||
| 1413 | ; | ||
| 1414 | ; Get the Linear address for DMAPhyAdr. There is a pte which always | ||
| 1415 | ; maps to this always. MapLinear translates DMAPhyAdr to a linear adr. | ||
| 1416 | ; | ||
| 1417 | ; | ||
| 1418 | ; 8/12/88 JHB removed _Copy16K, changed it to this routine. | ||
| 1419 | ; | ||
| 1420 | ;***************************************************************************** | ||
| 1421 | |||
| 1422 | _GetDMALinAdr proc near | ||
| 1423 | |||
| 1424 | push bp | ||
| 1425 | mov bp, sp | ||
| 1426 | push si | ||
| 1427 | push di | ||
| 1428 | push ds | ||
| 1429 | ; | ||
| 1430 | ; convert the DMAPhyAdr into a linear address. | ||
| 1431 | ; | ||
| 1432 | mov eax, dword ptr LArg1 | ||
| 1433 | call MapLinear | ||
| 1434 | ; | ||
| 1435 | ; eax = 32 bit linear adr for the DMA Xfer area. | ||
| 1436 | ; | ||
| 1437 | ror eax, 16 | ||
| 1438 | mov dx, ax | ||
| 1439 | ror eax, 16 ; dx:ax 32 bit linear adr to be returned | ||
| 1440 | |||
| 1441 | pop ds | ||
| 1442 | pop di | ||
| 1443 | pop si | ||
| 1444 | pop bp | ||
| 1445 | ret | ||
| 1446 | _GetDMALinAdr endp | ||
| 1447 | |||
| 1448 | ;****************************************************************************** | ||
| 1449 | ; | ||
| 1450 | ; set_selector - set up a selector address/attrib | ||
| 1451 | ; | ||
| 1452 | ; ENTRY: EAX = address for GDT selector - a linear address | ||
| 1453 | ; DI = GDT selector | ||
| 1454 | ; EXIT: selector in DI is writeable data segment,128k long and points | ||
| 1455 | ; to desired address. | ||
| 1456 | ; | ||
| 1457 | ;****************************************************************************** | ||
| 1458 | |||
| 1459 | set_selector proc near | ||
| 1460 | |||
| 1461 | push eax | ||
| 1462 | push di | ||
| 1463 | push es | ||
| 1464 | |||
| 1465 | and di,NOT 07h ; just in case... GDT entry | ||
| 1466 | push GDTD_GSEL | ||
| 1467 | pop es ; ES:DI -> selector entry | ||
| 1468 | |||
| 1469 | mov es:[di+2],ax ; low word of base address | ||
| 1470 | |||
| 1471 | shr eax,16 ; AX = high word of address | ||
| 1472 | mov es:[di+4],al ; low byte of high word of address | ||
| 1473 | xor al,al ; clear limit/G bit | ||
| 1474 | or al, 1 ; set LSB0 i.e. Limit16 bit for 128K Xfer | ||
| 1475 | mov es:[di+6],ax ; set high byte of high word of addr | ||
| 1476 | ; and high nibble of limit/G bit | ||
| 1477 | ; and Limit Bit 16 for 128K transfer | ||
| 1478 | mov ax,0FFFFh | ||
| 1479 | mov es:[di],ax ; set limit bits 0-15 | ||
| 1480 | |||
| 1481 | mov al,D_DATA0 ; writeable DATA seg / ring 0 | ||
| 1482 | mov es:[di+5],al | ||
| 1483 | |||
| 1484 | pop es | ||
| 1485 | pop di | ||
| 1486 | pop eax | ||
| 1487 | |||
| 1488 | ret | ||
| 1489 | |||
| 1490 | set_selector endp | ||
| 1491 | |||
| 1492 | ;**************************************************************************** | ||
| 1493 | ; _Exchange16K - called from C | ||
| 1494 | ; | ||
| 1495 | ; Exchange contents of the pages at LinAdr1 and LinAdr2 | ||
| 1496 | ; | ||
| 1497 | ; Exchange16K(LinAdr1, LinAdr2) | ||
| 1498 | ; long LinAdr1, LinAdr2; | ||
| 1499 | ; | ||
| 1500 | ; Written: JHB Aug 11, 1988 | ||
| 1501 | ; ISP Aug 12, 1988 Added cld. | ||
| 1502 | ; DWORD PTR mentioned explicitly | ||
| 1503 | ;***************************************************************************** | ||
| 1504 | |||
| 1505 | _Exchange16K proc near | ||
| 1506 | |||
| 1507 | push bp | ||
| 1508 | mov bp, sp | ||
| 1509 | push si | ||
| 1510 | push di | ||
| 1511 | push ds | ||
| 1512 | |||
| 1513 | mov di,MBSRC_GSEL ; source selector | ||
| 1514 | mov eax,dword ptr LArg1 ; load linear adr | ||
| 1515 | call set_selector ; set up a selector in GDT | ||
| 1516 | mov es,di | ||
| 1517 | |||
| 1518 | mov di,MBTAR_GSEL ; destination selector | ||
| 1519 | mov eax,dword ptr LArg2 | ||
| 1520 | call set_selector ; set up selector | ||
| 1521 | mov ds,di | ||
| 1522 | mov cx,1000h ; 16k bytes (4 at a time) | ||
| 1523 | xor di,di ; initialize index | ||
| 1524 | cld | ||
| 1525 | sloop: | ||
| 1526 | mov eax,dword ptr es:[di] ; pick a dword at LArg1 | ||
| 1527 | xchg eax,dword ptr ds:[di] ; swap with dword at LArg2 | ||
| 1528 | stosd ; store new dword at LArg1 | ||
| 1529 | loop sloop | ||
| 1530 | |||
| 1531 | pop ds | ||
| 1532 | pop di | ||
| 1533 | pop si | ||
| 1534 | pop bp | ||
| 1535 | ret | ||
| 1536 | |||
| 1537 | _Exchange16K endp | ||
| 1538 | |||
| 1539 | ; | ||
| 1540 | ; signals an exception error | ||
| 1541 | ; | ||
| 1542 | _FatalError proc near | ||
| 1543 | |||
| 1544 | push bp | ||
| 1545 | mov bp, sp | ||
| 1546 | |||
| 1547 | mov ax, 1 | ||
| 1548 | mov bx, 3 | ||
| 1549 | call ErrHndlr | ||
| 1550 | |||
| 1551 | pop bp | ||
| 1552 | ret | ||
| 1553 | |||
| 1554 | _FatalError endp | ||
| 1555 | |||
| 1556 | _TEXT ends ; end of segment | ||
| 1557 | |||
| 1558 | end ; end of module | ||
| 1559 | |||
| 1560 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/EM286LL.ASM b/v4.0/src/MEMM/MEMM/EM286LL.ASM new file mode 100644 index 0000000..3b3f72e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EM286LL.ASM | |||
| @@ -0,0 +1,360 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EM286LL - 386 routine to emulate 286 LOADALL | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMM286LL - 286 loadall emulation routine | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: April 11,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 04/16/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/18/86 0.01 Moved EL_Off before buffer | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 06/28/86 0.02 Modified CR0 logic & Edi for LL3 buffer | ||
| 31 | ; 07/03/86 0.03 Removed logic for enabling A20 watch | ||
| 32 | ; 07/06/86 0.04 Change assume to DGROUP | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | ; | ||
| 36 | ; Functional Description: | ||
| 37 | ; | ||
| 38 | ; 286 LOADALL is emulated by building a buffer for a | ||
| 39 | ; 386 LOADALL from the 286 LOADALL buffer (@80:0) and executing the 386 | ||
| 40 | ; LOADALL. | ||
| 41 | ; | ||
| 42 | ; | ||
| 43 | ;****************************************************************************** | ||
| 44 | .lfcond ; list false conditionals | ||
| 45 | .386p | ||
| 46 | page | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; P U B L I C D E C L A R A T I O N S | ||
| 49 | ;****************************************************************************** | ||
| 50 | ; | ||
| 51 | public EM286ll | ||
| 52 | public ELOff | ||
| 53 | ; | ||
| 54 | page | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; L O C A L C O N S T A N T S | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; | ||
| 59 | include loadall.inc | ||
| 60 | include VDMseg.inc | ||
| 61 | include desc.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | include instr386.inc | ||
| 64 | include vm386.inc | ||
| 65 | include oemdep.inc | ||
| 66 | |||
| 67 | FALSE equ 0 | ||
| 68 | TRUE equ not FALSE | ||
| 69 | |||
| 70 | ; | ||
| 71 | ; DescCopy | ||
| 72 | ; Macro for copying a 286 Loadall descriptor cache entry to a | ||
| 73 | ; 386 Loadall descriptor cache entry. | ||
| 74 | ; ENTRY: DS:SI pts to 286 Loadall descriptor entry | ||
| 75 | ; ES:DI pts to 386 Loadall descriptor entry | ||
| 76 | ; | ||
| 77 | ; EXIT: DS:SI unchanged. | ||
| 78 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 79 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 80 | ; | ||
| 81 | ; USED: EAX | ||
| 82 | ; | ||
| 83 | DescCopy MACRO | ||
| 84 | XOR_EAX_EAX ; clear EAX | ||
| 85 | mov ax,word ptr [si.dc2_BASEhi] ; AL = junk, AH = Access rights | ||
| 86 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 87 | OP32 | ||
| 88 | stosw ; store: junk->AR1,AR->AR2,0->AR3 & AR4 | ||
| 89 | OP32 | ||
| 90 | mov ax,[si] ; 24 bits of Base Addr from 286 entry | ||
| 91 | OP32 | ||
| 92 | and ax,0FFFFh ; AND EAX,00FFFFFFh | ||
| 93 | dw 000FFh ; clear high byte of base addr | ||
| 94 | call MapLinear ; Map address according to page tables | ||
| 95 | OP32 | ||
| 96 | stosw ; store Base Addr for 386 entry | ||
| 97 | XOR_EAX_EAX ; clear EAX | ||
| 98 | mov ax,[si.dc2_LIMIT] ; get low 16 bits of limit | ||
| 99 | OP32 | ||
| 100 | stosw ; store 32 bit LIMIT into 386 entry | ||
| 101 | ENDM | ||
| 102 | ; | ||
| 103 | ; CurCopy | ||
| 104 | ; Macro for copying a current descriptor cache entry to a | ||
| 105 | ; 386 Loadall descriptor cache entry. | ||
| 106 | ; ENTRY: DS:BX pts to current descriptor | ||
| 107 | ; ES:DI pts to 386 Loadall descriptor entry | ||
| 108 | ; | ||
| 109 | ; EXIT: DS:BX unchanged. | ||
| 110 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 111 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 112 | ; | ||
| 113 | ; USED: EAX | ||
| 114 | ; | ||
| 115 | CurCopy MACRO | ||
| 116 | OP32 | ||
| 117 | mov ax,[bx+4] ; get AR info | ||
| 118 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 119 | OP32 | ||
| 120 | stosw ; store into cache entry | ||
| 121 | mov ah,[bx+7] ; AX = Base[31..16] | ||
| 122 | OP32 | ||
| 123 | shl ax,16 ; high word of EAX = Base[31..16] | ||
| 124 | mov ax,[bx+2] ; EAX = Base[31..0] | ||
| 125 | OP32 | ||
| 126 | stosw | ||
| 127 | mov al,[bx+6] ; LIMIT[19..16] in low bits of AL | ||
| 128 | and ax,0Fh | ||
| 129 | OP32 | ||
| 130 | shl ax,16 ; high word of EAX = LIMIT[31..16] | ||
| 131 | ; NOTE: VDM does not use page | ||
| 132 | ; granularity for limit field !! | ||
| 133 | mov ax,[bx] ; EAX = LIMIT[31..0] | ||
| 134 | OP32 | ||
| 135 | stosw ; store into cache for 386 buffer | ||
| 136 | ENDM | ||
| 137 | ;****************************************************************************** | ||
| 138 | ; E X T E R N A L R E F E R E N C E S | ||
| 139 | ;****************************************************************************** | ||
| 140 | ; | ||
| 141 | L286BUFF segment at 80h | ||
| 142 | ; | ||
| 143 | ; Source 286 LoadAll buffer | ||
| 144 | ; | ||
| 145 | SLBuff LoadAllBuf286 <> ; 286 loadall buffer | ||
| 146 | |||
| 147 | L286BUFF ends | ||
| 148 | |||
| 149 | _TEXT segment | ||
| 150 | |||
| 151 | extrn MapLinear:near ; map linear address | ||
| 152 | extrn PortTrap:near ; IOBM trap set function (VMINIT) | ||
| 153 | |||
| 154 | _TEXT ends | ||
| 155 | |||
| 156 | ; | ||
| 157 | ;****************************************************************************** | ||
| 158 | ; L O C A L D A T A A R E A | ||
| 159 | ;****************************************************************************** | ||
| 160 | |||
| 161 | _DATA segment | ||
| 162 | |||
| 163 | ELOff dw offset ELbuff ; offset of 386 loadall buffer | ||
| 164 | ELbuff LoadAllBuf386 <> ; 386 loadall buffer | ||
| 165 | dd 0 ; filler - allow dword align | ||
| 166 | |||
| 167 | ;(0.03)extrn A20watch:byte ; Loadall/KBD A20 disable flag | ||
| 168 | |||
| 169 | _DATA ends | ||
| 170 | |||
| 171 | page | ||
| 172 | ;****************************************************************************** | ||
| 173 | ; S E G M E N T D E F I N I T I O N | ||
| 174 | ;****************************************************************************** | ||
| 175 | ; | ||
| 176 | _TEXT segment | ||
| 177 | ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP | ||
| 178 | |||
| 179 | ;****************************************************************************** | ||
| 180 | ; EM286ll - emulate 286 Loadall | ||
| 181 | ; | ||
| 182 | ; ENTRY: Protected Mode | ||
| 183 | ; physical address 80:0 holds 286 loadall buffer info | ||
| 184 | ; | ||
| 185 | ; EXIT: via Loadall to virtual mode | ||
| 186 | ; The 286 Loadall buffer is emulated with the following | ||
| 187 | ; exceptions: | ||
| 188 | ; The VM bit is set in EFLAGS. | ||
| 189 | ; The TR, IDT descriptor cache, & TSS descriptor cache are | ||
| 190 | ; pointed to the VDM entries. | ||
| 191 | ; | ||
| 192 | ; USED: | ||
| 193 | ; | ||
| 194 | ;****************************************************************************** | ||
| 195 | EM286ll proc near | ||
| 196 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 197 | mov ds,bx ; DS -> GDT | ||
| 198 | mov bx,800h ; BX = VM CS (segment form) | ||
| 199 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 200 | xor bx,bx | ||
| 201 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 202 | mov bx,VM1_GSEL | ||
| 203 | mov ds,bx ; DS:0 points to 286 loadall buffer | ||
| 204 | ASSUME DS:L286BUFF | ||
| 205 | ; | ||
| 206 | mov ax,VDMD_GSEL | ||
| 207 | mov es,ax | ||
| 208 | mov di,ES:[ELOff] ; ES:DI pts to 386 loadall buffer | ||
| 209 | ; | ||
| 210 | cld | ||
| 211 | ; | ||
| 212 | MOV_EAX_CR0 ; mov EAX,CR0 | ||
| 213 | and ax,0FFF1h ;clear current TS,EM, & MP bits | ||
| 214 | mov cx,[SLBuff.ll2_MSW] ; CX = 286 ll_buff MSW | ||
| 215 | and cx,000Eh ;retain 286 TS,EM, & MP bits | ||
| 216 | or ax,cx ; set client's TS,EM, & MP bits | ||
| 217 | OP32 | ||
| 218 | stosw ; store CR0 for 386 buffer | ||
| 219 | ; | ||
| 220 | OP32 | ||
| 221 | mov ax,0000h | ||
| 222 | dw 0002h ; VM bit on | ||
| 223 | mov ax,[SLBuff.ll2_FLAGS] ; get low word of flags | ||
| 224 | or ax,3000h ; set IOPL to 3 | ||
| 225 | OP32 | ||
| 226 | stosw ; store EFLAGS for 386 buffer | ||
| 227 | ; | ||
| 228 | XOR_EAX_EAX ; clear EAX | ||
| 229 | mov ax,[SLBuff.ll2_IP] ; get 286 IP - high word of EAX clear | ||
| 230 | OP32 | ||
| 231 | stosw ; store EIP for 386 buffer | ||
| 232 | ; | ||
| 233 | ; Copy the client's EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX | ||
| 234 | ; register images from his 386 loadall buffer to our 386 loadall buffer | ||
| 235 | ; | ||
| 236 | mov si,offset ll2_DI ; DS:SI pts to DI in 286 buffer | ||
| 237 | mov cx,8 | ||
| 238 | CopyGen: ; Copy General Purpose Registers | ||
| 239 | lodsw ; EAX = reg image from client's buffer | ||
| 240 | OP32 | ||
| 241 | stosw ; store it in our 386 buffer | ||
| 242 | loop CopyGen | ||
| 243 | |||
| 244 | ; | ||
| 245 | ; 386 debug registers | ||
| 246 | ; | ||
| 247 | MOV_EAX_DR6 | ||
| 248 | OP32 | ||
| 249 | stosw ; store DR6 in our 386 buffer | ||
| 250 | |||
| 251 | MOV_EAX_DR7 | ||
| 252 | OP32 | ||
| 253 | stosw ; store DR7 in our 386 buffer | ||
| 254 | ; | ||
| 255 | XOR_EAX_EAX ; clear EAX | ||
| 256 | ; | ||
| 257 | mov ax,TSS_GSEL ; get current TR for VDM's TSS !!! | ||
| 258 | OP32 | ||
| 259 | stosw ; store TR for 386 buffer | ||
| 260 | ; | ||
| 261 | mov si,offset ll2_LDT ; DS:SI pts to LDT in 286 buffer | ||
| 262 | lodsw ; get LDT entry from 286 buffer | ||
| 263 | OP32 | ||
| 264 | stosw ; store LDT for 386 buffer | ||
| 265 | |||
| 266 | OP32 | ||
| 267 | stosw ; store junk into GS for 386 buffer | ||
| 268 | |||
| 269 | OP32 | ||
| 270 | stosw ; store junk into FS for 386 buffer | ||
| 271 | |||
| 272 | ; | ||
| 273 | ; Copy the client's DS, SS, CS, ES register images from his 286 loadall | ||
| 274 | ; buffer to our 386 loadall buffer | ||
| 275 | ; | ||
| 276 | mov cx,4 | ||
| 277 | CopySeg: ; Copy Segment Registers | ||
| 278 | lodsw ; get seg image from client's buffer | ||
| 279 | OP32 | ||
| 280 | stosw ; store it in our 386 buffer | ||
| 281 | loop CopySeg | ||
| 282 | |||
| 283 | ; ES:DI pts to 386 TSS cache entry | ||
| 284 | ; | ||
| 285 | ; Copy the current TSS, IDT, & GDT descriptors from the GDT table to | ||
| 286 | ; our 386 loadall buffer | ||
| 287 | ; | ||
| 288 | push ds ; save client's buffer selector | ||
| 289 | mov ax,GDTD_GSEL | ||
| 290 | mov ds,ax | ||
| 291 | |||
| 292 | mov cx, 3 | ||
| 293 | mov bx, TSS_GSEL | ||
| 294 | push word ptr GDTD_GSEL | ||
| 295 | push word ptr IDTD_GSEL | ||
| 296 | |||
| 297 | CopyCur: ; Copy current descriptors | ||
| 298 | CurCopy ; DS:[BX] points to current descriptor | ||
| 299 | pop bx | ||
| 300 | loop CopyCur | ||
| 301 | mov ds, bx ; restore client's buffer selector | ||
| 302 | |||
| 303 | ; | ||
| 304 | ; ES:DI pts to 386 LDT cache entry | ||
| 305 | mov si,offset ll2_LDTcache ; DS:SI pts to 286 LDT cache entry | ||
| 306 | DescCopy ; store LDT cache for 386 buffer | ||
| 307 | ; | ||
| 308 | XOR_EAX_EAX ; clear EAX- use 0 for GS/FS caches | ||
| 309 | |||
| 310 | OP32 | ||
| 311 | stosw ; store GS cache for 386 buffer | ||
| 312 | OP32 | ||
| 313 | stosw | ||
| 314 | OP32 | ||
| 315 | stosw | ||
| 316 | ; | ||
| 317 | OP32 | ||
| 318 | stosw ; store FS cache for 386 buffer | ||
| 319 | OP32 | ||
| 320 | stosw | ||
| 321 | OP32 | ||
| 322 | stosw | ||
| 323 | ; | ||
| 324 | ; Copy the client's DS, SS, CS, ES register cache images from | ||
| 325 | ; his 286 loadall buffer to our 386 loadall buffer | ||
| 326 | ; | ||
| 327 | mov si,offset ll2_DScache ; DS:SI pts to 286 DS cache entry | ||
| 328 | mov cx,4 | ||
| 329 | CopyCac: ; ES:DI pts to our 386 ll cache entry | ||
| 330 | DescCopy ; store his cache in our 386 buffer | ||
| 331 | sub si,06h ; DS:SI pts to client's cache entry | ||
| 332 | loop CopyCac | ||
| 333 | ; | ||
| 334 | ; 386 Loadall buffer complete | ||
| 335 | ; | ||
| 336 | |||
| 337 | ;(0.03) push es | ||
| 338 | ;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap | ||
| 339 | ;(0.03) mov es, ax | ||
| 340 | ;(0.03) mov bh, 80h ; set every 1k | ||
| 341 | ;(0.03) mov ax, KbdDataPort | ||
| 342 | ;(0.03) call PortTrap ; set traps on keyboard ports | ||
| 343 | ;(0.03) mov ax, KbdCmdPort ; in case client | ||
| 344 | ;(0.03) call PortTrap ; tries to disable A20 | ||
| 345 | ;(0.03) pop es | ||
| 346 | ;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag | ||
| 347 | |||
| 348 | HwTabLock ; Hardware lock the high ram | ||
| 349 | |||
| 350 | OP32 | ||
| 351 | xor di,di ; clear EDI | ||
| 352 | mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer | ||
| 353 | dw LODAL386 ; execute 386 LOADALL | ||
| 354 | |||
| 355 | ASSUME DS:DGROUP | ||
| 356 | ; | ||
| 357 | EM286ll endp | ||
| 358 | |||
| 359 | _TEXT ends | ||
| 360 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/EM386LL.ASM b/v4.0/src/MEMM/MEMM/EM386LL.ASM new file mode 100644 index 0000000..3408eaa --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EM386LL.ASM | |||
| @@ -0,0 +1,397 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EM386LL - 386 routine to emulate 386 LOADALL | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EM386LL - 386 routine to emulate 386 LOADALL | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: April 11,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 04/16/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 29 | ; 06/29/86 0.02 Fixed error handler call. Error handler called | ||
| 30 | ; only on attempt to set VM bit in EFLAGS | ||
| 31 | ; 06/30/86 0.02 Jmp to error routine (instead of calling) | ||
| 32 | ; 07/03/86 0.03 Removed logic to enable A20 line watch | ||
| 33 | ; 07/05/86 0.04 JumpReal in R_CODE | ||
| 34 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 35 | ; 07/08/86 0.04 added DB67 NOPs to avoid B1 errata | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | ; | ||
| 39 | ; Functional Description: | ||
| 40 | ; | ||
| 41 | ; 386 LOADALL is emulated by building a buffer for a | ||
| 42 | ; 386 LOADALL from the client's 386 LOADALL buffer and executing the 386 | ||
| 43 | ; LOADALL. | ||
| 44 | ; | ||
| 45 | ; check DR6/DR7 for addresses > 1meg ? | ||
| 46 | ; | ||
| 47 | ;****************************************************************************** | ||
| 48 | .lfcond ; list false conditionals | ||
| 49 | .386p | ||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; P U B L I C D E C L A R A T I O N S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | public EM386ll | ||
| 56 | ; | ||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; L O C A L C O N S T A N T S | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; | ||
| 62 | include loadall.inc | ||
| 63 | include VDMseg.inc | ||
| 64 | include desc.inc | ||
| 65 | include VDMsel.inc | ||
| 66 | include instr386.inc | ||
| 67 | include vm386.inc | ||
| 68 | include oemdep.inc | ||
| 69 | |||
| 70 | FALSE equ 0 | ||
| 71 | TRUE equ not FALSE | ||
| 72 | |||
| 73 | ; | ||
| 74 | ; Desc3Copy | ||
| 75 | ; Macro for copying a 386 Loadall descriptor cache entry to a | ||
| 76 | ; 386 Loadall descriptor cache entry. | ||
| 77 | ; ENTRY: DS:ESI pts to client's 386 Loadall descriptor entry | ||
| 78 | ; ES:DI pts to our 386 Loadall descriptor entry | ||
| 79 | ; | ||
| 80 | ; EXIT: DS:ESI pts to byte after client's 386 ll descr entry (next entry). | ||
| 81 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 82 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 83 | ; | ||
| 84 | ; USED: EAX | ||
| 85 | ; | ||
| 86 | Desc3Copy MACRO | ||
| 87 | OP32 | ||
| 88 | EA32 ; EAX = dword from DS:[ESI] | ||
| 89 | lodsw ; get access rights | ||
| 90 | |||
| 91 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 92 | |||
| 93 | OP32 | ||
| 94 | stosw ; store access rights | ||
| 95 | |||
| 96 | OP32 | ||
| 97 | EA32 ; EAX = dword from DS:[ESI] | ||
| 98 | lodsw ; 32 bits of Base Addr from 386 entry | ||
| 99 | |||
| 100 | call MapLinear ; map this linear addr by page tables | ||
| 101 | |||
| 102 | OP32 | ||
| 103 | stosw ; store Base Addr for 386 entry | ||
| 104 | |||
| 105 | OP32 | ||
| 106 | EA32 ; EAX = dword from DS:[ESI] | ||
| 107 | lodsw ; get 32 bits of limit | ||
| 108 | |||
| 109 | OP32 | ||
| 110 | stosw ; store 32 bit LIMIT into 386 entry | ||
| 111 | ENDM | ||
| 112 | |||
| 113 | ; | ||
| 114 | ; CurCopy | ||
| 115 | ; Macro for copying a current descriptor cache entry to a | ||
| 116 | ; 386 Loadall descriptor cache entry. | ||
| 117 | ; ENTRY: DS:BX pts to current descriptor | ||
| 118 | ; ES:DI pts to 386 Loadall descriptor entry | ||
| 119 | ; | ||
| 120 | ; EXIT: DS:BX unchanged. | ||
| 121 | ; ES:DI pts to byte after 386 Loadall descriptor entry (next entry). | ||
| 122 | ; *** The access rights byte in set to DPL 3 for virtual mode *** | ||
| 123 | ; | ||
| 124 | ; USED: EAX | ||
| 125 | ; | ||
| 126 | CurCopy MACRO | ||
| 127 | OP32 | ||
| 128 | mov ax,[bx+4] ; get AR info | ||
| 129 | or ah,D_DPL3 ;* set DPL 3 for virtual mode access | ||
| 130 | OP32 | ||
| 131 | stosw ; store into cache entry | ||
| 132 | mov ah,[bx+7] ; AX = Base[31..16] | ||
| 133 | OP32 | ||
| 134 | shl ax,16 ; high word of EAX = Base[31..16] | ||
| 135 | mov ax,[bx+2] ; EAX = Base[31..0] | ||
| 136 | OP32 | ||
| 137 | stosw | ||
| 138 | mov al,[bx+6] ; LIMIT[19..16] in low bits of AL | ||
| 139 | and ax,0Fh | ||
| 140 | OP32 | ||
| 141 | shl ax,16 ; high word of EAX = LIMIT[31..16] | ||
| 142 | ; NOTE: VDM does not use page | ||
| 143 | ; granularity for limit field !! | ||
| 144 | mov ax,[bx] ; EAX = LIMIT[31..0] | ||
| 145 | OP32 | ||
| 146 | stosw ; store into cache for 386 buffer | ||
| 147 | ENDM | ||
| 148 | |||
| 149 | ;****************************************************************************** | ||
| 150 | ; L O C A L D A T A A R E A | ||
| 151 | ;****************************************************************************** | ||
| 152 | |||
| 153 | _DATA segment | ||
| 154 | extrn ELOff:word ; offset of 386 loadall buffer | ||
| 155 | _DATA ends | ||
| 156 | |||
| 157 | |||
| 158 | R_CODE segment | ||
| 159 | extrn JumpReal:far ; continue client in real mode (rrtrap.asm) | ||
| 160 | R_CODE ends | ||
| 161 | |||
| 162 | _TEXT segment | ||
| 163 | extrn MapLinear:near ; maps linear addresses (maplin.asm) | ||
| 164 | extrn PortTrap:near ; IOBM trap set function (vminit.asm) | ||
| 165 | extrn ErrHndlr:near ; error handler (errhndlr.asm) | ||
| 166 | _TEXT ends | ||
| 167 | |||
| 168 | |||
| 169 | page | ||
| 170 | ;****************************************************************************** | ||
| 171 | ; S E G M E N T D E F I N I T I O N | ||
| 172 | ;****************************************************************************** | ||
| 173 | ; | ||
| 174 | _TEXT segment | ||
| 175 | ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP | ||
| 176 | |||
| 177 | ;****************************************************************************** | ||
| 178 | ; EM386ll - emulate 386 Loadall | ||
| 179 | ; The basic approach here is to filter the client's loadall buffer into | ||
| 180 | ; a temporary buffer, setting our values for the parameters we don't want | ||
| 181 | ; him to change and then executing the 386 loadall from our buffer. | ||
| 182 | ; | ||
| 183 | ; ENTRY: Protected Mode | ||
| 184 | ; BP points to bottom of client's GPfault stack frame | ||
| 185 | ; ES(in GP frame):EDI points to the client's loadall buffer info | ||
| 186 | ; on stack: ESI,EBX,EBP | ||
| 187 | ; | ||
| 188 | ; EXIT: via Loadall to virtual mode | ||
| 189 | ; The 386 Loadall buffer is emulated with the following | ||
| 190 | ; exceptions: | ||
| 191 | ; The VM bit is set in EFLAGS. | ||
| 192 | ; The TR, IDT descriptor cache, & TSS descriptor cache are | ||
| 193 | ; pointed to the VDM entries. | ||
| 194 | ; | ||
| 195 | ; USED: Not applicable... loadall reloads all registers | ||
| 196 | ; | ||
| 197 | ;****************************************************************************** | ||
| 198 | EM386ll proc near | ||
| 199 | ; | ||
| 200 | PUSH_EAX | ||
| 201 | PUSH_ECX | ||
| 202 | PUSH_EDI | ||
| 203 | |||
| 204 | ; Build a descriptor to client's 386 loadall buffer | ||
| 205 | |||
| 206 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 207 | mov ds,bx ; DS -> GDT | ||
| 208 | mov bx, [bp.VTFOE+VMTF_ES] ; Get VM ES from GP stack frame | ||
| 209 | mov ax,bx | ||
| 210 | shl bx,4 ; BX = low 16 bits of base | ||
| 211 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 212 | shr ax, 4 ; AH = high 8 bits of base | ||
| 213 | mov ds:[VM1_GSEL+4],ah ; place in descriptor | ||
| 214 | |||
| 215 | ; Point DS:ESI to start of client's 386 loadall buffer | ||
| 216 | mov bx,VM1_GSEL | ||
| 217 | mov ds,bx | ||
| 218 | OP32 | ||
| 219 | mov si,di | ||
| 220 | ASSUME ds:nothing | ||
| 221 | |||
| 222 | ; Point ES:EDI to start of our 386 loadall buffer | ||
| 223 | |||
| 224 | mov ax,VDMD_GSEL | ||
| 225 | mov es,ax | ||
| 226 | OP32 | ||
| 227 | xor di,di ; clear EDI | ||
| 228 | mov di,ES:[ELOff] ; ES:EDI pts to our 386 loadall buffer | ||
| 229 | ; | ||
| 230 | cld | ||
| 231 | |||
| 232 | ; Walk through the two buffers in parallel, copying the client's values | ||
| 233 | ; when appropriate | ||
| 234 | |||
| 235 | ; | ||
| 236 | ; CR0 entry | ||
| 237 | ; | ||
| 238 | EA32 | ||
| 239 | OP32 | ||
| 240 | lodsw ; get client's CR0 | ||
| 241 | |||
| 242 | ;(0.02) OP32 | ||
| 243 | ;(0.02) test ax,0001h ; TEST EAX,80000001h | ||
| 244 | ;(0.02) dw 8000h ; Q: PG or PE bit set ? | ||
| 245 | ;(0.02) jz CR0_OK ; N: continue | ||
| 246 | ;(0.02) call Em386_Err ; Y: error | ||
| 247 | ; | ||
| 248 | CR0_OK: | ||
| 249 | MOV_ECX_CR0 | ||
| 250 | OP32 | ||
| 251 | and cx,0011h ; and ECX,80000011h | ||
| 252 | dw 8000h ; save only PG,ET, & PE bits | ||
| 253 | OP32 | ||
| 254 | or ax,cx ; or EAX,ECX | ||
| 255 | OP32 | ||
| 256 | stosw ; store CR0 for 386 buffer | ||
| 257 | XOR_ECX_ECX ; clear ECX | ||
| 258 | ; | ||
| 259 | ; EFLAGS | ||
| 260 | ; | ||
| 261 | EA32 | ||
| 262 | OP32 | ||
| 263 | lodsw ; get EFLAGS | ||
| 264 | ; | ||
| 265 | OP32 | ||
| 266 | test ax,0000h | ||
| 267 | dw 0002h ;Q: client's VM bit set ? | ||
| 268 | jz EF_OK ; N: continue | ||
| 269 | jmp Em386_Err ; Y: error handler - won't return here | ||
| 270 | EF_OK: | ||
| 271 | and ax,0FFFh ; clear IOPL & NT bits | ||
| 272 | OP32 | ||
| 273 | or ax,3000h | ||
| 274 | dw 0002h ; set VM bit and IOPL = 3 | ||
| 275 | OP32 | ||
| 276 | stosw ; store EFLAGS for 386 buffer | ||
| 277 | ; | ||
| 278 | ; Copy the client's EIP, EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX, DR6 & DR7 | ||
| 279 | ; register images from his 386 loadall buffer to our 386 loadall buffer | ||
| 280 | ; | ||
| 281 | mov cx,11 ; copy 11 register contents | ||
| 282 | OP32 ; dwords from DS:[ESI] to ES:[EDI] | ||
| 283 | EA32 | ||
| 284 | rep movsw ; copy 11 dwords | ||
| 285 | |||
| 286 | EA32 | ||
| 287 | nop ; this avoids a B1 errata | ||
| 288 | ; | ||
| 289 | ; store TR and LDTR | ||
| 290 | ; | ||
| 291 | XOR_EAX_EAX ; clear EAX | ||
| 292 | mov ax,TSS_GSEL ; get current TR for VDM's TSS !!! | ||
| 293 | OP32 | ||
| 294 | stosw ; store TR for 386 buffer | ||
| 295 | ; | ||
| 296 | sldt ax ; use current LDT | ||
| 297 | OP32 | ||
| 298 | stosw ; store LDTR for 386 buffer | ||
| 299 | ; | ||
| 300 | ; Copy the client's GS, FS, DS, SS, CS, ES register images from | ||
| 301 | ; his 386 loadall buffer to our 386 loadall buffer | ||
| 302 | ; | ||
| 303 | add si,offset ll3_GS - offset ll3_TSSR | ||
| 304 | mov cx,6 | ||
| 305 | OP32 ; dwords from DS:[ESI] to ES:[EDI] | ||
| 306 | EA32 | ||
| 307 | rep movsw ; copy 6 dwords | ||
| 308 | |||
| 309 | EA32 | ||
| 310 | nop ; this avoids a B1 errata | ||
| 311 | ; | ||
| 312 | ; Copy the current TSS, GDT, IDT, LDT descriptors from the GDT table to | ||
| 313 | ; our 386 loadall buffer | ||
| 314 | ; | ||
| 315 | push ds ; save client's buffer selector | ||
| 316 | mov ax,GDTD_GSEL | ||
| 317 | mov ds,ax | ||
| 318 | |||
| 319 | mov cx, 4 | ||
| 320 | mov bx, TSS_GSEL | ||
| 321 | push word ptr LDTD_GSEL | ||
| 322 | push word ptr GDTD_GSEL | ||
| 323 | push word ptr IDTD_GSEL | ||
| 324 | |||
| 325 | CopyCur: ; Copy current descriptors | ||
| 326 | CurCopy ; DS:[BX] points to current descriptor | ||
| 327 | pop bx | ||
| 328 | loop CopyCur | ||
| 329 | mov ds, bx ; restore client's buffer selector | ||
| 330 | |||
| 331 | ; DS:SI pts to 386 GS cache entry | ||
| 332 | ; | ||
| 333 | ; Copy the client's GS, FS, DS, SS, CS, ES register cache images from | ||
| 334 | ; his 386 loadall buffer to our 386 loadall buffer | ||
| 335 | ; | ||
| 336 | add si,offset ll3_GScache - offset ll3_TSScache | ||
| 337 | mov cx,6 | ||
| 338 | CopyCac: ; ES:DI pts to our 386 buf cache entry | ||
| 339 | Desc3Copy ; store his cache in our 386 buffer | ||
| 340 | loop CopyCac ; DS:SI pts to client's buf cache entry | ||
| 341 | |||
| 342 | ; | ||
| 343 | ; 386 Loadall buffer complete | ||
| 344 | ; | ||
| 345 | |||
| 346 | ;(0.03) push es | ||
| 347 | ;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap | ||
| 348 | ;(0.03) mov es, ax | ||
| 349 | ;(0.03) mov bh, 80h ; set every 1k | ||
| 350 | ;(0.03) mov ax, KbdDataPort | ||
| 351 | ;(0.03) call PortTrap ; set traps on keyboard ports | ||
| 352 | ;(0.03) mov ax, KbdCmdPort ; in case client | ||
| 353 | ;(0.03) call PortTrap ; tries to disable A20 | ||
| 354 | ;(0.03) pop es | ||
| 355 | ;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag | ||
| 356 | |||
| 357 | HwTabLock ; Hardware lock the high ram | ||
| 358 | |||
| 359 | OP32 | ||
| 360 | xor di,di ; XOR EDI,EDI - clear EDI | ||
| 361 | mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer | ||
| 362 | dw LODAL386 ; execute 386 LOADALL | ||
| 363 | |||
| 364 | ASSUME DS:DGROUP | ||
| 365 | ; | ||
| 366 | ; | ||
| 367 | EM386ll endp | ||
| 368 | |||
| 369 | page | ||
| 370 | ;****************************************************************************** | ||
| 371 | ; Em386_Err - handle 386 ll emulation error | ||
| 372 | ; This routine is currently called only on attempts to set the | ||
| 373 | ; VM bit via loadall. | ||
| 374 | ;****************************************************************************** | ||
| 375 | Em386_Err proc near | ||
| 376 | push ax | ||
| 377 | push bx | ||
| 378 | mov ax, PrivErr | ||
| 379 | mov bx, Err3LL | ||
| 380 | call ErrHndlr | ||
| 381 | pop bx | ||
| 382 | pop bx | ||
| 383 | ; | ||
| 384 | ; continue client in real mode | ||
| 385 | ; | ||
| 386 | POP_EDI ; restore used regs | ||
| 387 | POP_ECX | ||
| 388 | POP_EAX | ||
| 389 | ; stack back to VmFault exit condition | ||
| 390 | |||
| 391 | jmp JumpReal ; "jump" to real mode and continue interrupted | ||
| 392 | ; code. | ||
| 393 | |||
| 394 | Em386_Err endp | ||
| 395 | ; | ||
| 396 | _TEXT ends | ||
| 397 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/EMM.ASM b/v4.0/src/MEMM/MEMM/EMM.ASM new file mode 100644 index 0000000..557afa4 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM.ASM | |||
| @@ -0,0 +1,522 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EMM - Expanded Memory Manager interface for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMM - Expanded Memory Manager interface | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 14, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 06/14/86 original | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; 06/29/86 0.02 Protect port 84/85 from ints | ||
| 29 | ; 07/05/86 0.04 moved EMM_rEntry to R_CODE | ||
| 30 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 31 | ; 07/08/86 0.04 Changed EMM_pEntry to call EMM functions | ||
| 32 | ; directly | ||
| 33 | ; 07/10/86 0.05 jmp $+2 before "POPF" | ||
| 34 | ; 07/10/86 0.05 added EMM_Flag | ||
| 35 | ; 06/09/88 remove _map_known since there is no map now (pc) | ||
| 36 | ; 07/20/88 remove debugger code (pc) | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | ; Functional Description: | ||
| 40 | ; The module contains code for calling the EMM functions and a routine | ||
| 41 | ; for managing the AUTO mode of MEMM. | ||
| 42 | ; There are two EMM entry points in this module; one for real/virtual | ||
| 43 | ; mode entry and one for protected mode (IDT entry points here). When | ||
| 44 | ; MEMM is ON (system in Virtual mode), INT 67H calls transition to protected | ||
| 45 | ; mode and the EMM_pEntry entry point. EMM_pEntry sets up the same stack | ||
| 46 | ; conditions as the generic int67_Entry dispatcher and calls the appropriate | ||
| 47 | ; EMM function. Some EMM functions cannot be executed in protected mode. | ||
| 48 | ; These functions are called by reflecting the INT 67H to the real/virtual | ||
| 49 | ; mode entry point. EMM functions which are executed in PROTECTED mode | ||
| 50 | ; will take less time (they don't suffer the extra time to reflect the | ||
| 51 | ; INT 67H). | ||
| 52 | ; | ||
| 53 | ;****************************************************************************** | ||
| 54 | .lfcond | ||
| 55 | .386p | ||
| 56 | page | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; P U B L I C D E C L A R A T I O N S | ||
| 59 | ;****************************************************************************** | ||
| 60 | ; | ||
| 61 | public EMM_pEntry ; protected mode entry point | ||
| 62 | public EMM_rEntry ; real mode entry point | ||
| 63 | public EMM_rEfix ; label for far jump to int67_entry | ||
| 64 | public _AutoUpdate ; update auto mode of VDM/EMM | ||
| 65 | public EMM_Flag ; flag for EMM calls | ||
| 66 | |||
| 67 | page | ||
| 68 | ;****************************************************************************** | ||
| 69 | ; L O C A L C O N S T A N T S | ||
| 70 | ;****************************************************************************** | ||
| 71 | ; | ||
| 72 | include vdmseg.inc | ||
| 73 | include vdmsel.inc | ||
| 74 | include vm386.inc | ||
| 75 | ; include instr386.inc | ||
| 76 | include oemdep.inc | ||
| 77 | include emmdef.inc | ||
| 78 | |||
| 79 | FALSE equ 0 | ||
| 80 | TRUE equ not FALSE | ||
| 81 | |||
| 82 | ; | ||
| 83 | ; these EMM functions are handled in protected mode | ||
| 84 | ; | ||
| 85 | EMM_MAP_PAGE equ 44h ; map handle page | ||
| 86 | EMM_RESTORE equ 48h ; restore page map | ||
| 87 | EMM_GET_SET equ 4Eh ; get/set page map | ||
| 88 | EMM_GET_SET_PARTIAL equ 4Fh ; get/set partial page map | ||
| 89 | EMM_MAP_PAGE_ARRAY equ 50h ; map handle page array | ||
| 90 | EMM_ALTER_MAP_JUMP equ 55h ; alter mapping and jump | ||
| 91 | EMM_ALTER_MAP_CALL equ 56h ; alter mapping and call | ||
| 92 | EMM_MOVE_XCHG_MEM equ 57h ; move/xchg memory region | ||
| 93 | EMM_ALTER_MAP_REG_SET equ 5Bh ; alternate map register set | ||
| 94 | |||
| 95 | EMM_HW_MALFUNCTION equ 81h ; | ||
| 96 | |||
| 97 | ;****************************************************************************** | ||
| 98 | ; E X T E R N A L R E F E R E N C E S | ||
| 99 | ;****************************************************************************** | ||
| 100 | ; | ||
| 101 | ABS0 segment use16 at 0000h | ||
| 102 | |||
| 103 | org 67h * 4 ; EMM function interrupt | ||
| 104 | EMMVec dw ? ; offset of vector | ||
| 105 | dw ? ; segment of vector | ||
| 106 | |||
| 107 | ABS0 ends | ||
| 108 | |||
| 109 | _DATA segment | ||
| 110 | |||
| 111 | extrn _EMMstatus:word | ||
| 112 | extrn Active_Status:byte ; current VDM status | ||
| 113 | extrn Auto_Mode:byte ; current Auto mode status | ||
| 114 | ;extrn _map_known:byte ; non-zero => I/O map known to a user | ||
| 115 | extrn _handle_count:word ; number of active EMM handles | ||
| 116 | extrn _regp:word ; pointer to args on stack | ||
| 117 | |||
| 118 | _DATA ends | ||
| 119 | |||
| 120 | _TEXT segment | ||
| 121 | |||
| 122 | extrn int67_Entry:far ; it's far because we need CS on stack too | ||
| 123 | extrn GoVirtual:near | ||
| 124 | extrn ErrHndlr:near | ||
| 125 | extrn hw_int:near | ||
| 126 | extrn RRProc:near | ||
| 127 | |||
| 128 | extrn _GetStatus:near | ||
| 129 | extrn _GetPageFrameAddress:near | ||
| 130 | extrn _GetUnallocatedPageCount:near | ||
| 131 | extrn _AllocatePages:near | ||
| 132 | extrn _MapHandlePage:near | ||
| 133 | extrn _DeallocatePages:near | ||
| 134 | extrn _GetEMMVersion:near | ||
| 135 | extrn _SavePageMap:near | ||
| 136 | extrn _RestorePageMap:near | ||
| 137 | extrn _GetPageMappingRegisterIOArray:near | ||
| 138 | extrn _GetLogicalToPhysicalPageTrans:near | ||
| 139 | extrn _GetEMMHandleCount:near | ||
| 140 | extrn _GetEMMHandlePages:near | ||
| 141 | extrn _GetAllEMMHandlePages:near | ||
| 142 | extrn _GetSetPageMap:near | ||
| 143 | |||
| 144 | extrn _GetSetPartial:near | ||
| 145 | extrn _MapHandleArray:near | ||
| 146 | extrn _AlterMapAndJump:near | ||
| 147 | extrn _AlterMapAndCall:near | ||
| 148 | extrn _MoveExchangeMemory:near | ||
| 149 | extrn _AlternateMapRegisterSet:near | ||
| 150 | |||
| 151 | _TEXT ends | ||
| 152 | |||
| 153 | page | ||
| 154 | ;****************************************************************************** | ||
| 155 | ; S E G M E N T D E F I N I T I O N | ||
| 156 | ;****************************************************************************** | ||
| 157 | ; | ||
| 158 | _DATA segment | ||
| 159 | EMM_Flag db 0 ; non-zero => EMM function called by our code | ||
| 160 | _DATA ends | ||
| 161 | |||
| 162 | page | ||
| 163 | ;****************************************************************************** | ||
| 164 | ; | ||
| 165 | ; _TEXT Code Segment | ||
| 166 | ; | ||
| 167 | ;****************************************************************************** | ||
| 168 | ; | ||
| 169 | _TEXT segment | ||
| 170 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 171 | ;****************************************************************************** | ||
| 172 | ; protected mode dispatch table | ||
| 173 | ; allocate(43h)/deallocate(45h) pages and get I/O map (49h) | ||
| 174 | ; MUST be reflected to Virtual mode | ||
| 175 | ; MapHandlePage,RestorePageMap,GetSetPageMap,GetSetPartial, | ||
| 176 | ; MapHandleArray,MoveExchangeMemory,AlterMapAndJump, | ||
| 177 | ; AlterMapAndCall and AlternateMapRegisterSet are protected mode ONLY. | ||
| 178 | ;****************************************************************************** | ||
| 179 | EpE_Dispatch label word | ||
| 180 | dw offset _TEXT:EpE_Null | ||
| 181 | dw offset _TEXT:EpE_Null | ||
| 182 | dw offset _TEXT:EpE_Null | ||
| 183 | dw offset _TEXT:EpE_Null | ||
| 184 | dw offset _TEXT:_MapHandlePage ;44h | ||
| 185 | dw offset _TEXT:EpE_Null | ||
| 186 | dw offset _TEXT:EpE_Null | ||
| 187 | dw offset _TEXT:EpE_Null | ||
| 188 | dw offset _TEXT:_RestorePageMap ;48h | ||
| 189 | dw offset _TEXT:EpE_Null | ||
| 190 | dw offset _TEXT:EpE_Null | ||
| 191 | dw offset _TEXT:EpE_Null | ||
| 192 | dw offset _TEXT:EpE_Null | ||
| 193 | dw offset _TEXT:EpE_Null | ||
| 194 | dw offset _TEXT:_GetSetPageMap ;4eh | ||
| 195 | dw offset _TEXT:_GetSetPartial ;4fh | ||
| 196 | dw offset _TEXT:_MapHandleArray ;50h | ||
| 197 | dw offset _TEXT:EpE_Null | ||
| 198 | dw offset _TEXT:EpE_Null | ||
| 199 | dw offset _TEXT:EpE_Null | ||
| 200 | dw offset _TEXT:EpE_Null | ||
| 201 | dw offset _TEXT:_AlterMapAndJump ;55h | ||
| 202 | dw offset _TEXT:_AlterMapAndCall ;56h | ||
| 203 | dw offset _TEXT:_MoveExchangeMemory ;57h | ||
| 204 | dw offset _TEXT:EpE_Null | ||
| 205 | dw offset _TEXT:EpE_Null | ||
| 206 | dw offset _TEXT:EpE_Null | ||
| 207 | dw offset _TEXT:_AlternateMapRegisterSet ;5bh | ||
| 208 | dw offset _TEXT:EpE_Null | ||
| 209 | dw offset _TEXT:EpE_Null | ||
| 210 | |||
| 211 | page | ||
| 212 | ;****************************************************************************** | ||
| 213 | ; EMM_pEntry - protected mode entry point for EMM function calls | ||
| 214 | ; | ||
| 215 | ; ENTRY: Protected mode | ||
| 216 | ; DGROUP:[EMM_Flag] = zero => reflect this int | ||
| 217 | ; SS:[SP] pointing to virtual mode INT stack frame | ||
| 218 | ; | ||
| 219 | ; EXIT: Protected mode | ||
| 220 | ; if this EMM function is to be handled in protected mode, | ||
| 221 | ; registers as set by EMM functions | ||
| 222 | ; else | ||
| 223 | ; reflect int 67 to virtual mode EMM code | ||
| 224 | ; | ||
| 225 | ; NOTE: ***** | ||
| 226 | ; Allocate(43h)/deallocate(44h) pages and get I/O map (49h) | ||
| 227 | ; MUST be reflected to Virtual mode. | ||
| 228 | ; | ||
| 229 | ; USED: none | ||
| 230 | ; | ||
| 231 | ;****************************************************************************** | ||
| 232 | ; | ||
| 233 | ; reflect EMM function to real mode | ||
| 234 | ; | ||
| 235 | EpE_reflect: | ||
| 236 | push 67h ; refect | ||
| 237 | jmp hw_int ; it... | ||
| 238 | ; | ||
| 239 | ; | ||
| 240 | ; client not in Virtual mode | ||
| 241 | ; | ||
| 242 | EpE_not_VM: | ||
| 243 | pop ebp ; N: call error handler | ||
| 244 | |||
| 245 | mov ax,ExcpErr ; exception error | ||
| 246 | mov bx,ErrINTProt ; invalid software interrupt | ||
| 247 | call ErrHndlr | ||
| 248 | ; | ||
| 249 | ; function entry | ||
| 250 | ; | ||
| 251 | EMM_pEntry proc near | ||
| 252 | ; | ||
| 253 | push ebp | ||
| 254 | mov bp,sp | ||
| 255 | test [bp.VTFO+VMTF_EFLAGShi],2 ;Q:client in Virtual mode ? | ||
| 256 | jz EpE_not_VM ; N: handle it | ||
| 257 | ; Y: check flag | ||
| 258 | push VDMD_GSEL | ||
| 259 | pop ds ; DS = DGROUP | ||
| 260 | push VDMD_GSEL | ||
| 261 | pop es ; ES = DGROUP | ||
| 262 | cmp [EMM_Flag],0 ;Q: did we do this int67 ? | ||
| 263 | je EpE_Reflect ; N: reflect it | ||
| 264 | mov [EMM_Flag],0 ; Y: clear EMM_Flag for next | ||
| 265 | ; time and handle function | ||
| 266 | ; in protected mode. | ||
| 267 | ; | ||
| 268 | ; dispatch EMM function OR reflect to real/vm dispatcher | ||
| 269 | ; | ||
| 270 | EpE_chk_func: | ||
| 271 | HwTabUnlock ; unlock ROM | ||
| 272 | |||
| 273 | push [bp.VTFO+VMTF_FS] ; client FS | ||
| 274 | push [bp.VTFO+VMTF_GS] ; client GS | ||
| 275 | push [bp.VTFO+VMTF_ES] ; client ES | ||
| 276 | push [bp.VTFO+VMTF_DS] ; client DS | ||
| 277 | push [bp.VTFO+VMTF_EFLAGS] ; client Flag | ||
| 278 | push [bp.VTFO+VMTF_CS] ; client CS | ||
| 279 | push word ptr [bp.VTFO+VMTF_EIP] ; client IP (low word of EIP) | ||
| 280 | ; stack has - IP,CS,PFlag,DS,ES,GS,FS | ||
| 281 | pushad ; all regs saved | ||
| 282 | mov bp,sp ; SS:BP -> to stack args (see r67_Frame struc) | ||
| 283 | mov [_regp],sp ; regp points to regs on stack | ||
| 284 | mov [_regp+2],ss ; regp now has a far ptr to regs | ||
| 285 | |||
| 286 | push ax | ||
| 287 | mov ax, PFLAG_VIRTUAL ; Faked VM bit | ||
| 288 | or [bp.PFlag], ax ; Incorpated in PFlag | ||
| 289 | pop ax | ||
| 290 | ; | ||
| 291 | ; validate function code | ||
| 292 | ; | ||
| 293 | sub ah,40h ; check if entry code too small | ||
| 294 | jb EpE_inv_exit ; if so, error exit | ||
| 295 | cmp ah,(5Dh-40h) ; check if entry code too big | ||
| 296 | ja EpE_inv_exit ; if so, error exit | ||
| 297 | ; else, AH = 0 base function # | ||
| 298 | ; | ||
| 299 | ; call through the jump table | ||
| 300 | ; | ||
| 301 | EpE_jump: | ||
| 302 | xchg ah,al ; AL = function code | ||
| 303 | mov si,ax | ||
| 304 | xchg ah,al ; AH = function code again | ||
| 305 | and si,00FFh ; SI = function # | ||
| 306 | shl si,1 ; SI = table offset | ||
| 307 | call CS:EpE_Dispatch[si] ; call function | ||
| 308 | |||
| 309 | ; | ||
| 310 | ; check to see if we need to patch CS:IP on the iretd stack frame | ||
| 311 | ; | ||
| 312 | EpE_Exit: | ||
| 313 | test word ptr [bp.PFlag], PFLAG_PATCH_CS_IP | ||
| 314 | jz EpE_No_Patch | ||
| 315 | |||
| 316 | mov bp, sp ; use bp to address stack | ||
| 317 | ; | ||
| 318 | ; patch iretd's CS:EIP to new CS:IP on stack | ||
| 319 | ; | ||
| 320 | mov ax, [bp.retaddr] ; get return IP | ||
| 321 | mov [bp.rFS+6], ax ; iretd's IP (6 bytes beyond FS) | ||
| 322 | xor ax, ax | ||
| 323 | mov [bp.rFS+8], ax ; zero high word of EIP | ||
| 324 | mov ax, [bp.rCS] ; get return CS | ||
| 325 | mov [bp.rFS+10], ax ; iretd's CS | ||
| 326 | |||
| 327 | EpE_No_Patch: | ||
| 328 | popad ; restore regs | ||
| 329 | add sp, 6 ; throw away return addr cs and ip and flags | ||
| 330 | pop [bp.VTFO+VMTF_DS] ; client DS | ||
| 331 | pop [bp.VTFO+VMTF_ES] ; client ES | ||
| 332 | pop [bp.VTFO+VMTF_GS] ; client GS | ||
| 333 | pop [bp.VTFO+VMTF_FS] ; client FS | ||
| 334 | |||
| 335 | |||
| 336 | pop ebp ; restore bp | ||
| 337 | |||
| 338 | HwTabLock ; lock ROM | ||
| 339 | |||
| 340 | iretd ; return to virtual mode caller | ||
| 341 | ; | ||
| 342 | ; Null function - do nothing (should not get to here) | ||
| 343 | EpE_Null: | ||
| 344 | ret ; return after doing nothing | ||
| 345 | ; | ||
| 346 | ; EMM error handling | ||
| 347 | ; | ||
| 348 | EpE_inv_exit: ; set invalid function code error | ||
| 349 | mov byte ptr [bp.rAX+1],INVALID_FUNCTION | ||
| 350 | jmp EpE_Exit | ||
| 351 | |||
| 352 | EMM_pEntry endp | ||
| 353 | |||
| 354 | page | ||
| 355 | ;****************************************************************************** | ||
| 356 | ; EMM_rLink - real/virtual mode link for EMM function calls from | ||
| 357 | ; R_CODE segment. | ||
| 358 | ; | ||
| 359 | ; ENTRY: real/virtual mode | ||
| 360 | ; all registers as set by user | ||
| 361 | ; | ||
| 362 | ; EXIT: real/virtual mode | ||
| 363 | ; registers as set by EMM functions | ||
| 364 | ; | ||
| 365 | ; USED: none | ||
| 366 | ; | ||
| 367 | ;****************************************************************************** | ||
| 368 | EMM_rLINK proc far | ||
| 369 | |||
| 370 | ; | ||
| 371 | ; check for protected mode ONLY function | ||
| 372 | ; | ||
| 373 | cmp ah,EMM_MAP_PAGE ;Q: map handle page function ? | ||
| 374 | je ErE_GoProt ; Y: do it in protected mode | ||
| 375 | cmp ah,EMM_RESTORE ;Q: restore page map function ? | ||
| 376 | je ErE_GoProt ; Y: do it in protected mode | ||
| 377 | cmp ah,EMM_GET_SET ;Q: get/set page map function ? | ||
| 378 | je ErE_GoProt ; Y: do it in protected mode | ||
| 379 | cmp ah,EMM_GET_SET_PARTIAL ;Q: get/set partial function ? | ||
| 380 | je ErE_GoProt ; Y: do it in protected mode | ||
| 381 | cmp ah,EMM_MAP_PAGE_ARRAY ;Q: map handle page array ? | ||
| 382 | je ErE_GoProt ; Y: do it in protected mode | ||
| 383 | cmp ah,EMM_ALTER_MAP_JUMP ;Q: alter map and jump ? | ||
| 384 | je ErE_GoProt ; Y: do it in protected mode | ||
| 385 | cmp ah,EMM_ALTER_MAP_CALL ;Q: alter map and call ? | ||
| 386 | je ErE_GoProt ; Y: do it in protected mode | ||
| 387 | cmp ah,EMM_MOVE_XCHG_MEM ;Q: move/xchg memory region ? | ||
| 388 | je ErE_GoProt ; Y: do it in protected mode | ||
| 389 | cmp ah,EMM_ALTER_MAP_REG_SET;Q: alternate map register set ? | ||
| 390 | je ErE_GoProt ; Y: do it in protected mode | ||
| 391 | ; N: do it in real/virtual mode | ||
| 392 | ; | ||
| 393 | ; here for real/virtual mode functions | ||
| 394 | ; | ||
| 395 | push fs | ||
| 396 | push gs | ||
| 397 | push es | ||
| 398 | push ds | ||
| 399 | push 00 ; PFlag => real mode call to EMM functions | ||
| 400 | push seg DGROUP | ||
| 401 | pop ds ; set DS = DGROUP | ||
| 402 | call int67_Entry ; call dispatcher | ||
| 403 | add sp,2 ; drop PFlag arg | ||
| 404 | pop ds ; restore seg regs | ||
| 405 | pop es | ||
| 406 | pop gs | ||
| 407 | pop fs | ||
| 408 | ret ; and return | ||
| 409 | |||
| 410 | ; | ||
| 411 | ; Here if protected mode function called via real IDT | ||
| 412 | ; - set EMM flag and go for it... | ||
| 413 | ; | ||
| 414 | ErE_GoProt: | ||
| 415 | push ds | ||
| 416 | push seg DGROUP | ||
| 417 | pop ds ; DS = DGROUP | ||
| 418 | cmp [Active_Status],0 ;Q: are we in Virtual Mode ? | ||
| 419 | jne ErE_Pcall ; Y: call protected mode function | ||
| 420 | ; mov [_map_known],TRUE ; N: set global auto mode flag | ||
| 421 | call _AutoUpdate ; go into virtual mode | ||
| 422 | ; and call function | ||
| 423 | ErE_Pcall: | ||
| 424 | mov [EMM_Flag],TRUE ; set flag | ||
| 425 | pop ds ; restore DS | ||
| 426 | int 67h ; go for it ... | ||
| 427 | ret ; then return | ||
| 428 | |||
| 429 | EMM_rLINK endp | ||
| 430 | |||
| 431 | page | ||
| 432 | ;****************************************************************************** | ||
| 433 | ; _AutoUpdate - updates the EMM status when in AutoMode | ||
| 434 | ; | ||
| 435 | ; ENTRY: REAL or VIRTUAL mode ONLY | ||
| 436 | ; DS = DGROUP segment | ||
| 437 | ; DS:[Auto_Mode] = non-zero => system currently in auto mode | ||
| 438 | ; DS:[Active_Status] = non-zero => system currently ON | ||
| 439 | ; DS:[_map_known] = non-zero => I/O map has been given to a user | ||
| 440 | ; | ||
| 441 | ; EXIT: exits in real or virtual depending on the state variables | ||
| 442 | ; DS:[Active_Status] = current ON/OFF status | ||
| 443 | ; | ||
| 444 | ; USED: none | ||
| 445 | ; | ||
| 446 | ;****************************************************************************** | ||
| 447 | _AutoUpdate proc near | ||
| 448 | ; | ||
| 449 | cmp [Auto_Mode],0 ;Q: in Auto mode now ? | ||
| 450 | je AU_exit ; N: exit | ||
| 451 | cmp [Active_Status],0 ; Y:Q: ON now ? | ||
| 452 | je AU_chkoff ; N: check OFF state status | ||
| 453 | ; | ||
| 454 | ; here if we are currently ON | ||
| 455 | ; | ||
| 456 | ; cmp [_map_known],0 ; Y:Q: map known ? | ||
| 457 | ; jne AU_exit ; Y: then stay ON... | ||
| 458 | cmp [_handle_count],0 ; N:Q: any active handles ? | ||
| 459 | jne AU_exit ; Y: then stay ON... | ||
| 460 | mov [Active_Status],0 ; N: go to OFF state | ||
| 461 | push ax | ||
| 462 | call RRProc ; Force processor into real mode | ||
| 463 | pop ax | ||
| 464 | jmp AU_exit ; and leave in real mode | ||
| 465 | ; | ||
| 466 | ; here if we are currently OFF | ||
| 467 | ; | ||
| 468 | AU_chkoff: | ||
| 469 | cmp [_handle_count],0 ;Q: any active handles ? | ||
| 470 | je AU_exit ; N: stay off | ||
| 471 | |||
| 472 | ; cmp [_map_known],0 ;; Q: is the map known ? | ||
| 473 | ; je AU_exit ;; N: then stay OFF... | ||
| 474 | |||
| 475 | AU_ON: ; Y: turn ON EMM | ||
| 476 | mov [Active_Status],1 ; go to ON state, | ||
| 477 | call GoVirtual ; and go to virtual mode (ON) | ||
| 478 | AU_exit: | ||
| 479 | ret | ||
| 480 | ; | ||
| 481 | _AutoUpdate endp | ||
| 482 | |||
| 483 | _TEXT ends | ||
| 484 | |||
| 485 | page | ||
| 486 | ;****************************************************************************** | ||
| 487 | ; | ||
| 488 | ; R_CODE Code Segment | ||
| 489 | ; | ||
| 490 | ;****************************************************************************** | ||
| 491 | ; | ||
| 492 | R_CODE segment | ||
| 493 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 494 | |||
| 495 | page | ||
| 496 | ;****************************************************************************** | ||
| 497 | ; EMM_rEntry - real/virtual mode entry point for EMM function calls | ||
| 498 | ; | ||
| 499 | ; ENTRY: real/virtual mode | ||
| 500 | ; all registers as set by user | ||
| 501 | ; | ||
| 502 | ; EXIT: real/virtual mode | ||
| 503 | ; registers as set by EMM functions | ||
| 504 | ; | ||
| 505 | ; USED: none | ||
| 506 | ; | ||
| 507 | ;****************************************************************************** | ||
| 508 | EMM_rEntry proc near | ||
| 509 | ; | ||
| 510 | cli ; just in case pushf/call far | ||
| 511 | |||
| 512 | EMM_rEfix: | ||
| 513 | call EMM_rLink ; call _TEXT segment link | ||
| 514 | iret ; return to caller | ||
| 515 | ; | ||
| 516 | EMM_rEntry endp | ||
| 517 | |||
| 518 | |||
| 519 | R_CODE ends | ||
| 520 | |||
| 521 | end | ||
| 522 | |||
diff --git a/v4.0/src/MEMM/MEMM/EMM386.INC b/v4.0/src/MEMM/MEMM/EMM386.INC new file mode 100644 index 0000000..2b1143c --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM386.INC | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: EMM386.INC - general includes for MEMM | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: May 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change Log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION Description | ||
| 22 | ; -------- -------- -------------------------------------------- | ||
| 23 | ; 04/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | ; | ||
| 32 | ; Message Flag Equates | ||
| 33 | ; | ||
| 34 | INC_PRC_MSG equ 00000001b ; Incorrect processor type message | ||
| 35 | INC_DOS_MSG equ 00000010b ; Incorrect DOS message | ||
| 36 | MEM_ERR_MSG equ 00000100b ; Memory error message | ||
| 37 | INS_ERR_MSG equ 00001000b ; Already Installed message | ||
| 38 | NO_PF_MSG equ 00010000b ; Nowhere to put PF message | ||
| 39 | SIZE_ADJ_MSG equ 00100000b ; EMM Pool size adjusted message | ||
| 40 | BASE_ADJ_MSG equ 01000000b ; Page Frame Base adjusted msg | ||
| 41 | MAPA_ADJ_MSG equ 10000000b ; Map register address adjusted msg | ||
| 42 | INV_PARM_MSG equ 100000000b ; Invalid parameter message | ||
| 43 | PF_WARN_MSG equ 1000000000b ; PF located over ROM warning message | ||
| 44 | ; | ||
| 45 | ; These messages cause MEMM to not install | ||
| 46 | ; | ||
| 47 | KILLER_MSG = INC_PRC_MSG+INC_DOS_MSG+MEM_ERR_MSG+INS_ERR_MSG+NO_PF_MSG | ||
| 48 | ; | ||
| 49 | .list ; end of EMM386.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/EMM386.LNK b/v4.0/src/MEMM/MEMM/EMM386.LNK new file mode 100644 index 0000000..f48b430 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM386.LNK | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | memm386+ | ||
| 2 | elimfunc+ | ||
| 3 | emm+ | ||
| 4 | emmmes+ | ||
| 5 | emminit+ | ||
| 6 | memmonf+ | ||
| 7 | init+ | ||
| 8 | m_state+ | ||
| 9 | rom_srch+ | ||
| 10 | ppage+ | ||
| 11 | allocmem+ | ||
| 12 | inittab+ | ||
| 13 | shiphi+ | ||
| 14 | extpool+ | ||
| 15 | vdminit+ | ||
| 16 | i286+ | ||
| 17 | i386+ | ||
| 18 | tabdef+ | ||
| 19 | trapdef+ | ||
| 20 | vmtrap+ | ||
| 21 | vminst+ | ||
| 22 | elimtrap+ | ||
| 23 | iotrap+ | ||
| 24 | a20trap+ | ||
| 25 | oemproc+ | ||
| 26 | initepg+ | ||
| 27 | vminit+ | ||
| 28 | em286ll+ | ||
| 29 | em386ll+ | ||
| 30 | moveb+ | ||
| 31 | maplin+ | ||
| 32 | retreal+ | ||
| 33 | rrtrap+ | ||
| 34 | errhndlr+ | ||
| 35 | ekbd+ | ||
| 36 | util+ | ||
| 37 | initdeb+ | ||
| 38 | mapdma | ||
| 39 | emm386.exe | ||
| 40 | emm386.map/m | ||
| 41 | ..\emm\emmlib.lib | ||
diff --git a/v4.0/src/MEMM/MEMM/EMM386D.LNK b/v4.0/src/MEMM/MEMM/EMM386D.LNK new file mode 100644 index 0000000..fd07081 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMM386D.LNK | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | memm386+ | ||
| 2 | elimfunc+ | ||
| 3 | emmD+ | ||
| 4 | emmmes+ | ||
| 5 | emminit+ | ||
| 6 | memmonf+ | ||
| 7 | init+ | ||
| 8 | rom_srch+ | ||
| 9 | ppage+ | ||
| 10 | allocmem+ | ||
| 11 | inittab+ | ||
| 12 | vdminitD+ | ||
| 13 | i286+ | ||
| 14 | i386+ | ||
| 15 | tabdefD+ | ||
| 16 | trapdef+ | ||
| 17 | kbd+ | ||
| 18 | print+ | ||
| 19 | vmtrapD+ | ||
| 20 | vminstD+ | ||
| 21 | elimtrap+ | ||
| 22 | iotrap+ | ||
| 23 | a20trap+ | ||
| 24 | oemproc+ | ||
| 25 | initepg+ | ||
| 26 | vminit+ | ||
| 27 | em286ll+ | ||
| 28 | em386ll+ | ||
| 29 | moveb+ | ||
| 30 | maplin+ | ||
| 31 | retreal+ | ||
| 32 | rrtrap+ | ||
| 33 | errhndlr+ | ||
| 34 | ekbd+ | ||
| 35 | util+ | ||
| 36 | initdebD+ | ||
| 37 | mapdma | ||
| 38 | emm386d.exe | ||
| 39 | emm386d.map/m | ||
| 40 | ..\deb386\buglib.lib ..\emm\emmlib.lib | ||
| 41 | |||
diff --git a/v4.0/src/MEMM/MEMM/EMMCOM.LNK b/v4.0/src/MEMM/MEMM/EMMCOM.LNK new file mode 100644 index 0000000..a1b6a4d --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMMCOM.LNK | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | memmcom+ | ||
| 2 | memmonf | ||
| 3 | emmcom.exe | ||
| 4 | emmcom.map/m; | ||
| 5 | |||
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 | |||
| 59 | FALSE equ 0 | ||
| 60 | TRUE equ not FALSE | ||
| 61 | |||
| 62 | EMM_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 | |||
| 70 | extrn pool_size:word ; size of EMM Pages Pool in kbytes | ||
| 71 | extrn xbase_addr_h:byte ; bit 16-24 of address of first byte of emm memory | ||
| 72 | extrn xbase_addr_l:word ; bit 0-15 of address of first byte of emm memory | ||
| 73 | extrn sys_size:word ; number of 16k pages taken away from conv. mem | ||
| 74 | extrn PageT_Seg:word ; segment of system page table | ||
| 75 | |||
| 76 | extrn _PF_Base:word ; segment addr of page frame base | ||
| 77 | extrn _page_frame_pages:word ; number of pages in 3.2 page frame | ||
| 78 | |||
| 79 | extrn _EMMstatus:word ; status of EMM | ||
| 80 | |||
| 81 | extrn _page_frame_base:word ; pointers into page tables for each window | ||
| 82 | extrn _mappable_pages:word ; mappable page array | ||
| 83 | extrn _EMM_MPindex:byte ; index into mappable page array | ||
| 84 | extrn _physical_page_count:word ; number of physical pages | ||
| 85 | extrn _mappable_page_count:word ; number of mappable pages | ||
| 86 | |||
| 87 | extrn _cntxt_pages:word ; pages in a context | ||
| 88 | extrn _cntxt_bytes:word ; bytes in a context | ||
| 89 | |||
| 90 | extrn _emm_page:word ; ptr to array of EMM pages | ||
| 91 | extrn _free_count:word ; # of free EMM pages | ||
| 92 | extrn _emmpt_start:word ; start of empty part of emm page | ||
| 93 | extrn _emm_free:word ; ptr to array of free EMM pages | ||
| 94 | extrn _free_top:word ; top of _emm_free | ||
| 95 | |||
| 96 | extrn _total_pages:word ; total # of EMM pages available | ||
| 97 | extrn _pft386:word ; ptr to array of page table entries | ||
| 98 | |||
| 99 | extrn _emm_brk:word ; offset for emm data break address | ||
| 100 | |||
| 101 | extrn FRS_array:word ; | ||
| 102 | extrn CurRegSetn:byte | ||
| 103 | extrn CurRegSet:word | ||
| 104 | extrn FRS_free:byte | ||
| 105 | |||
| 106 | extrn _handle_table:word | ||
| 107 | extrn _handle_count:word | ||
| 108 | |||
| 109 | _DATA ends | ||
| 110 | |||
| 111 | ifndef NOHIMEM | ||
| 112 | else | ||
| 113 | VDATA segment | ||
| 114 | extrn vdata_begin:byte | ||
| 115 | VDATA ends | ||
| 116 | endif | ||
| 117 | |||
| 118 | LAST segment | ||
| 119 | extrn mappable_segs:byte | ||
| 120 | LAST ends | ||
| 121 | |||
| 122 | _TEXT segment | ||
| 123 | extrn InitELIM:far | ||
| 124 | _TEXT ends | ||
| 125 | |||
| 126 | LAST segment | ||
| 127 | extrn InitEPage:near | ||
| 128 | LAST 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 | ;****************************************************************************** | ||
| 155 | Get_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 | ;****************************************************************************** | ||
| 171 | init_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 | ;****************************************************************************** | ||
| 198 | init_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 | ;****************************************************************************** | ||
| 223 | init_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 | ;****************************************************************************** | ||
| 248 | inv_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 | ; | ||
| 261 | LAST segment USE16 | ||
| 262 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 263 | |||
| 264 | ;****************************************************************************** | ||
| 265 | ; LOCAL VARIABLES | ||
| 266 | ;****************************************************************************** | ||
| 267 | first_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 | ;****************************************************************************** | ||
| 292 | EMM_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 | |||
| 321 | ifndef NOHIMEM | ||
| 322 | else | ||
| 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 | ||
| 328 | endif | ||
| 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 | ||
| 350 | EMMP_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 | ||
| 361 | EMIN_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 ; | ||
| 372 | EMIN_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 | ; | ||
| 379 | EMIN_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 | ; | ||
| 440 | EMIN_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 | ; | ||
| 456 | EMIN_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 | ||
| 479 | EMIN_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 | ||
| 498 | EMIN_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 | ||
| 526 | EMIN_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 | ||
| 545 | EMIN_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 | ; | ||
| 673 | EMM_Init endp | ||
| 674 | |||
| 675 | ; | ||
| 676 | LAST ends | ||
| 677 | |||
| 678 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/EMMMES.ASM b/v4.0/src/MEMM/MEMM/EMMMES.ASM new file mode 100644 index 0000000..1036a66 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EMMMES.ASM | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title EMMMES - messages for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EMMMES - messages for MEMM | ||
| 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 | ; 05/24/86 Original | ||
| 27 | ; 06/26/86 0.02 changed version #. | ||
| 28 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 29 | ; 07/06/86 0.04 changed version #. | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 31 | ; 07/06/86 0.04 moved some messages to LAST | ||
| 32 | ; 07/08/86 0.04 Changed messages for incorrect machine | ||
| 33 | ; 07/09/86 0.05 changed version displayed version# to 3.20. | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | .lfcond | ||
| 37 | .386p | ||
| 38 | page | ||
| 39 | ;****************************************************************************** | ||
| 40 | ; P U B L I C D E C L A R A T I O N S | ||
| 41 | ;****************************************************************************** | ||
| 42 | ; | ||
| 43 | public InitMess | ||
| 44 | public InstallMess | ||
| 45 | public ISizeMess | ||
| 46 | public ExtSizeMess | ||
| 47 | public SysSizeMess | ||
| 48 | public PFBAMess | ||
| 49 | public ActiveMess | ||
| 50 | public InactiveMess | ||
| 51 | public AutoMess | ||
| 52 | public POE_Mess | ||
| 53 | public POE_Num | ||
| 54 | public POE_Len | ||
| 55 | public EXCPE_Mess | ||
| 56 | public EXCPE_Num | ||
| 57 | public EXCPE_CS | ||
| 58 | public EXCPE_EIP | ||
| 59 | public EXCPE_ERR | ||
| 60 | public EXCPE_Len | ||
| 61 | public InvParm | ||
| 62 | public InvPFBA | ||
| 63 | public InvMRA | ||
| 64 | public Adj_Size | ||
| 65 | public InsfMem | ||
| 66 | public Incorrect_DOS | ||
| 67 | public Incorrect_PRT | ||
| 68 | public Already_Inst | ||
| 69 | public PFWarning | ||
| 70 | public No_PF_Avail | ||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; L O C A L C O N S T A N T S | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; | ||
| 76 | include ascii_sm.equ | ||
| 77 | include vdmseg.inc | ||
| 78 | |||
| 79 | page | ||
| 80 | ;****************************************************************************** | ||
| 81 | ; S E G M E N T D E F I N I T I O N | ||
| 82 | ;****************************************************************************** | ||
| 83 | |||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | ; LAST Segment messages | ||
| 87 | ; | ||
| 88 | ;****************************************************************************** | ||
| 89 | ; | ||
| 90 | LAST segment | ||
| 91 | |||
| 92 | InitMess db CR,LF | ||
| 93 | db "MICROSOFT Expanded Memory Manager 386 Version 4.00",CR,LF | ||
| 94 | db "(C) Copyright MICROSOFT Corporation 1988",CR,LF | ||
| 95 | db "$" | ||
| 96 | |||
| 97 | InstallMess db "EMM386 Installed.", CR,LF | ||
| 98 | db " Extended memory allocated: " | ||
| 99 | ExtSizeMess db " KB",CR,LF | ||
| 100 | db " System memory allocated: " | ||
| 101 | SysSizeMess db " KB",CR,LF | ||
| 102 | db " " | ||
| 103 | db "--------",CR,LF | ||
| 104 | db " Expanded memory available: " | ||
| 105 | ISizeMess db " KB",CR,LF | ||
| 106 | db " Page frame base address: " | ||
| 107 | PFBAMess db "XX000 H",CR,LF | ||
| 108 | db "$" | ||
| 109 | |||
| 110 | ActiveMess db "EMM386 Active.",CR,LF | ||
| 111 | db CR,LF | ||
| 112 | db "$" | ||
| 113 | |||
| 114 | InactiveMess db "EMM386 Inactive.",CR,LF | ||
| 115 | db CR,LF | ||
| 116 | db "$" | ||
| 117 | |||
| 118 | AutoMess db "EMM386 is in Auto mode.",CR,LF | ||
| 119 | db CR,LF | ||
| 120 | db "$" | ||
| 121 | |||
| 122 | ; | ||
| 123 | ; install error messages | ||
| 124 | ; | ||
| 125 | |||
| 126 | InvParm db "Invalid parameter specified.",CR,LF | ||
| 127 | db "$" | ||
| 128 | |||
| 129 | InvPFBA db "Page Frame Base Address adjusted.",CR,LF | ||
| 130 | db "$" | ||
| 131 | |||
| 132 | InvMRA db "Mapping Register Address adjusted.",CR,LF | ||
| 133 | db "$" | ||
| 134 | |||
| 135 | Adj_Size db "Size of expanded memory pool adjusted.",CR,LF | ||
| 136 | db "$" | ||
| 137 | |||
| 138 | PFWarning db "WARNING - " | ||
| 139 | db "Option ROM or RAM detected within page frame." | ||
| 140 | db CR,LF | ||
| 141 | db CR,LF | ||
| 142 | db BEL | ||
| 143 | db "$" | ||
| 144 | |||
| 145 | InsfMem db "EMM386 not installed - insufficient memory.",CR,LF | ||
| 146 | db BEL | ||
| 147 | db CR,LF | ||
| 148 | db "$" | ||
| 149 | |||
| 150 | Incorrect_DOS db "EMM386 not installed - incorrect DOS version.",CR,LF | ||
| 151 | db BEL | ||
| 152 | db CR,LF | ||
| 153 | db "$" | ||
| 154 | |||
| 155 | Incorrect_PRT db "EMM386 not installed - incorrect machine type.",CR,LF | ||
| 156 | db BEL | ||
| 157 | db CR,LF | ||
| 158 | db "$" | ||
| 159 | |||
| 160 | No_PF_Avail db "EMM386 not installed - " | ||
| 161 | db "unable to set page frame base address.",CR,LF | ||
| 162 | db BEL | ||
| 163 | db CR,LF | ||
| 164 | db "$" | ||
| 165 | |||
| 166 | Already_Inst db "EMM386 already installed.",CR,LF | ||
| 167 | db BEL | ||
| 168 | db CR,LF | ||
| 169 | db "$" | ||
| 170 | |||
| 171 | LAST ends | ||
| 172 | |||
| 173 | page | ||
| 174 | ;****************************************************************************** | ||
| 175 | ; | ||
| 176 | ; _DATA Segment messages | ||
| 177 | ; | ||
| 178 | ;****************************************************************************** | ||
| 179 | ; | ||
| 180 | _DATA segment | ||
| 181 | |||
| 182 | ; | ||
| 183 | ; run time error messages | ||
| 184 | ; | ||
| 185 | POE_Mess db CR,LF | ||
| 186 | db BEL | ||
| 187 | db "EMM386 Privileged operation error #" | ||
| 188 | POE_Num db "xx -",CR,LF | ||
| 189 | db "Deactivate EMM386 and Continue (C) or reBoot (B)" | ||
| 190 | db " (C or B) ? " | ||
| 191 | POE_Len = $-POE_Mess | ||
| 192 | db "$" | ||
| 193 | |||
| 194 | EXCPE_Mess db CR,LF | ||
| 195 | db BEL | ||
| 196 | db "EMM386 Exception error #" | ||
| 197 | EXCPE_Num db "xx @" | ||
| 198 | EXCPE_CS db "xxxx:" | ||
| 199 | EXCPE_EIP db "xxxxxxxx Code " | ||
| 200 | EXCPE_ERR db "xxxx" | ||
| 201 | db CR,LF,"Press enter to reboot" | ||
| 202 | EXCPE_Len = $-EXCPE_Mess | ||
| 203 | db "$" | ||
| 204 | |||
| 205 | ; | ||
| 206 | _DATA ends | ||
| 207 | |||
| 208 | end | ||
| 209 | |||
| 210 | |||
diff --git a/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM b/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM new file mode 100644 index 0000000..a675868 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ERRHNDLR.ASM | |||
| @@ -0,0 +1,385 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE ErrHndlr - Error Handler | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 8 | ; | ||
| 9 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 10 | ; | ||
| 11 | ; Module: ErrHndlr - Recover from exception and priveledged operation errors | ||
| 12 | ; | ||
| 13 | ; Version: 0.04 | ||
| 14 | ; | ||
| 15 | ; Date: June 6,1986 | ||
| 16 | ; | ||
| 17 | ; Authors: Brad Tate | ||
| 18 | ; | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; CHANGES: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION DESCRIPTION | ||
| 24 | ; -------- -------- ------------------------------------------------------ | ||
| 25 | ; 06/06/86 Original | ||
| 26 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 27 | ; 06/28/86 0.02 Removed STI at end of ErrHndlr | ||
| 28 | ; 06/28/86 0.02 Changed error # display to leading zeroes | ||
| 29 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | page | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional description: | ||
| 36 | ; | ||
| 37 | ; This module contains the code that displays an error message and | ||
| 38 | ; asks the user to continue or reboot. | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | page | ||
| 42 | .386P | ||
| 43 | ; | ||
| 44 | include vdmseg.inc | ||
| 45 | include vdmsel.inc | ||
| 46 | include vm386.inc | ||
| 47 | include kbd.inc | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; Public Declarations | ||
| 50 | ;****************************************************************************** | ||
| 51 | ; | ||
| 52 | public ErrHndlr ; Display message and continue or reboot | ||
| 53 | public Error_Flag | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; Externs | ||
| 56 | ;****************************************************************************** | ||
| 57 | _TEXT segment | ||
| 58 | extrn RetReal:near ; return to real mode | ||
| 59 | extrn egetc:near ; get keyboard character | ||
| 60 | extrn WaitKBD:near ; wait for keyboard ready | ||
| 61 | _TEXT ends | ||
| 62 | |||
| 63 | _DATA segment | ||
| 64 | extrn powr10:word ; power of 10's table | ||
| 65 | extrn POE_Mess:byte ; privileged operation error | ||
| 66 | extrn POE_Num:byte ; where to put error code | ||
| 67 | extrn POE_Len:abs ; length of message | ||
| 68 | extrn EXCPE_Mess:byte ; exception error message | ||
| 69 | extrn EXCPE_Num:byte ; where to put error code | ||
| 70 | extrn EXCPE_CS:byte ; where to put CS | ||
| 71 | extrn EXCPE_EIP:byte ; where to put EIP | ||
| 72 | extrn EXCPE_ERR:byte ; where to put ERR | ||
| 73 | extrn EXCPE_Len:abs ; length of message | ||
| 74 | _DATA ends | ||
| 75 | ; | ||
| 76 | romdata segment use16 at 40h | ||
| 77 | org 71h | ||
| 78 | fBreak db ? | ||
| 79 | fReset dw ? | ||
| 80 | romdata ends | ||
| 81 | ; | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; Equates | ||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | MASTER = 0A1H ; Master interrupt i/o port | ||
| 87 | SLAVE = 021H ; Slave interrupt i/o port | ||
| 88 | NMI = 070H ; Non-Maskable interrupt i/o port | ||
| 89 | DIS_MSTSLV = 00H ; Value to write to disable master/slave | ||
| 90 | DIS_NMI = 080H ; Value to write to disable NMI | ||
| 91 | ENA_NMI = 008H ; Value to write to enable NMI | ||
| 92 | B = 48 ; make code for B | ||
| 93 | C = 46 ; make code for C | ||
| 94 | ENTER = 28 ; make code for enter key | ||
| 95 | ATTR = 07 ; attribute for write string | ||
| 96 | WRSTR = 1301h ; write string function code (format 1) | ||
| 97 | CPOSN = 5*256+0 ; cursor position to write | ||
| 98 | ; | ||
| 99 | ; | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; LOCAL DATA | ||
| 102 | ;****************************************************************************** | ||
| 103 | _DATA segment | ||
| 104 | Error_Flag dw 0 ; flags for Instruction Prefixes | ||
| 105 | masterp db 0 ; save master port value | ||
| 106 | slavep db 0 ; save slave port value | ||
| 107 | mode db 0 ; save mode | ||
| 108 | boot db 0 ; value to reboot | ||
| 109 | continue db 0 ; value to continue | ||
| 110 | |||
| 111 | GPsavERR dw 0 ; GP fault Error Code save | ||
| 112 | GPsavEIP dd 0 ; GP fault EIP save | ||
| 113 | GPsavCS dw 0 ; GP fault CS save | ||
| 114 | |||
| 115 | _DATA ends | ||
| 116 | ; | ||
| 117 | ;****************************************************************************** | ||
| 118 | ; | ||
| 119 | ; ErrHndlr - displays the appropriate error message and prompts the | ||
| 120 | ; user for a character to continue or reboot. The screen | ||
| 121 | ; is cleared by this routine. If the user chooses to | ||
| 122 | ; continue, the system is in real mode. | ||
| 123 | ; | ||
| 124 | ; entry: ax = 0 => Privileged operation error | ||
| 125 | ; ax = 1 => Exception error | ||
| 126 | ; bx = error number to display | ||
| 127 | ; | ||
| 128 | ; exit: either reboot, or exit in "real" mode with CLI | ||
| 129 | ; | ||
| 130 | ; used: none | ||
| 131 | ; | ||
| 132 | ; stack: | ||
| 133 | ; | ||
| 134 | ;****************************************************************************** | ||
| 135 | _TEXT segment | ||
| 136 | ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP | ||
| 137 | ErrHndlr proc near | ||
| 138 | ; | ||
| 139 | ; save fault infos | ||
| 140 | ; | ||
| 141 | push eax | ||
| 142 | push ds | ||
| 143 | push VDMD_GSEL | ||
| 144 | pop ds | ||
| 145 | mov eax, dword ptr [bp.VTFO] ; error code | ||
| 146 | mov [GPsavERR], ax | ||
| 147 | mov eax, dword ptr [bp.VTFOE+VMTF_EIP] ; EIP | ||
| 148 | mov [GPsavEIP], eax | ||
| 149 | mov ax, word ptr [bp.VTFOE+VMTF_CS] ; CS | ||
| 150 | mov [GPsavCS], ax | ||
| 151 | pop ds | ||
| 152 | pop eax | ||
| 153 | |||
| 154 | call RetReal ; return to real mode | ||
| 155 | ; | ||
| 156 | push ax | ||
| 157 | push bx | ||
| 158 | push cx | ||
| 159 | push dx | ||
| 160 | push bp | ||
| 161 | push di | ||
| 162 | ; | ||
| 163 | push ax ; save input to this routine | ||
| 164 | in al,MASTER ; get value of master interrupt port | ||
| 165 | mov [masterp],al ; save it | ||
| 166 | in al,SLAVE ; get value of slave interrupt port | ||
| 167 | mov [slavep],al ; save it | ||
| 168 | mov al,DIS_MSTSLV ; value to disable master/slave int | ||
| 169 | out MASTER,al ; disable master | ||
| 170 | out SLAVE,al ; disable slave | ||
| 171 | mov al,DIS_NMI ; value to disable NMI | ||
| 172 | out NMI,al | ||
| 173 | kbdbusy: | ||
| 174 | call egetc ; q: is there stuff in keyboard buffer? | ||
| 175 | jnz kbdbusy ; y: get it and pitch it | ||
| 176 | ; n: continue | ||
| 177 | pop ax ; get entry condition | ||
| 178 | or ax,ax ; q: privileged error? | ||
| 179 | jnz excep ; n: exception error | ||
| 180 | mov bp,offset DGROUP:POE_Mess ; y: privileged error | ||
| 181 | mov cx,POE_Len | ||
| 182 | mov di,offset DGROUP:POE_Num; error number location | ||
| 183 | mov ax,bx ; error number in ax | ||
| 184 | call b2asc10 ; convert to ascii | ||
| 185 | mov [boot],B ; key to boot | ||
| 186 | mov [continue],C ; key to continue | ||
| 187 | jmp skip_exc ; skip exception stuff | ||
| 188 | excep: | ||
| 189 | mov bp,offset DGROUP:EXCPE_Mess ; n: load up exception error | ||
| 190 | mov cx,EXCPE_Len ; length of msg | ||
| 191 | mov di,offset DGROUP:EXCPE_Num ; error number location | ||
| 192 | mov ax,bx ; error number in ax | ||
| 193 | call b2asc10 ; convert to ascii | ||
| 194 | mov di,offset DGROUP:EXCPE_CS | ||
| 195 | mov ax,[GPsavCS] | ||
| 196 | call b2asc16 | ||
| 197 | mov di,offset DGROUP:EXCPE_EIP | ||
| 198 | mov eax,[GPsavEIP] | ||
| 199 | ror eax,16 | ||
| 200 | call b2asc16 | ||
| 201 | ror eax,16 | ||
| 202 | call b2asc16 | ||
| 203 | mov di,offset DGROUP:EXCPE_ERR | ||
| 204 | mov ax,[GPsavERR] | ||
| 205 | call b2asc16 | ||
| 206 | mov [boot],ENTER ; key to reboot | ||
| 207 | mov [continue],0ffh ; can't continue | ||
| 208 | skip_exc: | ||
| 209 | mov ah,0fh ; read video state | ||
| 210 | int 10h | ||
| 211 | mov [mode],al ; save mode | ||
| 212 | ; mov ax,3 ; set to mode 3 | ||
| 213 | ; int 10h ; standard 80 x 25 color | ||
| 214 | mov dx,CPOSN ; cursor position | ||
| 215 | mov bl,ATTR ; attribute | ||
| 216 | mov ax,WRSTR ; write string function code | ||
| 217 | int 10h ; do it | ||
| 218 | cli ; make sure int 10 didn't enable | ||
| 219 | key_loop: | ||
| 220 | call egetc ; get a character | ||
| 221 | jz key_loop ; nothing there yet | ||
| 222 | cmp al,[continue] ; q: continue? | ||
| 223 | je err_cont ; y | ||
| 224 | cmp al,[boot] ; q: boot? | ||
| 225 | jne key_loop ; n: try again | ||
| 226 | ;****************************************************************************** | ||
| 227 | ; | ||
| 228 | ; Reboot system | ||
| 229 | ; | ||
| 230 | ;****************************************************************************** | ||
| 231 | assume ds:romdata | ||
| 232 | mov ax,romdata | ||
| 233 | mov ds,ax ; ds = romdata segment | ||
| 234 | mov [freset],0 ; cold restart | ||
| 235 | mov al,0fh or 80h ; shutdown byte address/disable NMI | ||
| 236 | out 70h,al ; write CMOS address | ||
| 237 | jmp short $+2 ; delay | ||
| 238 | mov al,0h ; shutdown code 0 = processor reset | ||
| 239 | out 71h,al ; write shutdown code to shutdown byte | ||
| 240 | call WaitKBD ; wait for 8042 to accept command | ||
| 241 | mov al,0feh ; feh = pulse output bit 0 (reset) | ||
| 242 | out KbStatus,al ; reset processor | ||
| 243 | hlt | ||
| 244 | assume ds:DGROUP | ||
| 245 | ; | ||
| 246 | err_cont: | ||
| 247 | xor ah,ah ; ah = 0 to set video mode | ||
| 248 | mov al,[mode] ; restore their mode | ||
| 249 | int 10h | ||
| 250 | cli ; turn them off... | ||
| 251 | ; | ||
| 252 | ; restore master, slave, and NMI | ||
| 253 | ; | ||
| 254 | mov al,[masterp] ; get value of master interrupt port | ||
| 255 | out MASTER,al ; restore it | ||
| 256 | mov al,[slavep] ; get value of slave interrupt port | ||
| 257 | out SLAVE,al ; restore it | ||
| 258 | mov al,ENA_NMI ; value to enable NMI | ||
| 259 | out NMI,al | ||
| 260 | ; | ||
| 261 | pop di | ||
| 262 | pop bp | ||
| 263 | pop dx | ||
| 264 | pop cx | ||
| 265 | pop bx | ||
| 266 | pop ax | ||
| 267 | ret | ||
| 268 | ErrHndlr endp | ||
| 269 | |||
| 270 | page | ||
| 271 | ;****************************************************************************** | ||
| 272 | ; | ||
| 273 | ; b2asc10 - converts binary to ascii decimal and store at _TEXT:DI | ||
| 274 | ; stores 2 ascii chars (decimal # is right justified and | ||
| 275 | ; filled on left with 0s) | ||
| 276 | ; | ||
| 277 | ; entry: ax = binary number | ||
| 278 | ; ds:DGROUP | ||
| 279 | ; ds:di = place to store ascii chars. | ||
| 280 | ; | ||
| 281 | ; exit: ASCII decimal representation of number stored at _TEXT:DI | ||
| 282 | ; | ||
| 283 | ; used: none | ||
| 284 | ; | ||
| 285 | ; stack: | ||
| 286 | ; | ||
| 287 | ;****************************************************************************** | ||
| 288 | ; | ||
| 289 | b2asc10 proc near | ||
| 290 | ; | ||
| 291 | push ax | ||
| 292 | push bx | ||
| 293 | push cx | ||
| 294 | push dx | ||
| 295 | push si | ||
| 296 | push di | ||
| 297 | ; | ||
| 298 | mov si,2 ; pointer to base 10 table | ||
| 299 | mov bl,1 ; leading zeroes on | ||
| 300 | ; | ||
| 301 | ; convert binary number to decimal ascii | ||
| 302 | ; | ||
| 303 | b2_loop: | ||
| 304 | xor dx,dx ; clear word extension | ||
| 305 | mov cx,powr10[si] | ||
| 306 | div cx ; divide by power of 10 | ||
| 307 | or bl,bl | ||
| 308 | jnz b2_ascii | ||
| 309 | ; | ||
| 310 | or ax,ax ; q: zero result? | ||
| 311 | jnz b2_ascii ; n: go convert to ascii | ||
| 312 | ; | ||
| 313 | mov al,' ' ; y: go blank fill | ||
| 314 | jmp b2_make_strg ; | ||
| 315 | ; | ||
| 316 | b2_ascii: | ||
| 317 | add al,'0' ; put into ascii format | ||
| 318 | mov bl,1 ; leading zeroes on | ||
| 319 | ; | ||
| 320 | b2_make_strg: | ||
| 321 | mov ds:[di],al ; put ascii number into string | ||
| 322 | xchg ax,dx | ||
| 323 | inc di ; increment buffer string pointer | ||
| 324 | dec si ; decrement power of 10 pointer | ||
| 325 | dec si ; | ||
| 326 | jge b2_loop ; Q: Last digit? N: Jump if not | ||
| 327 | ; | ||
| 328 | pop di | ||
| 329 | pop si | ||
| 330 | pop dx | ||
| 331 | pop cx | ||
| 332 | pop bx | ||
| 333 | pop ax | ||
| 334 | ret ; *** return *** | ||
| 335 | ; | ||
| 336 | b2asc10 endp | ||
| 337 | ; | ||
| 338 | ;****************************************************************************** | ||
| 339 | ; | ||
| 340 | ; b2asc16 - converts binary to hexidecimal and store at _TEXT:DI | ||
| 341 | ; stores 4 ascii chars (# is right justified and | ||
| 342 | ; filled on left with 0s) | ||
| 343 | ; | ||
| 344 | ; entry: ax = binary number | ||
| 345 | ; ds:DGROUP | ||
| 346 | ; ds:di = place to store ascii chars. | ||
| 347 | ; | ||
| 348 | ; exit: ASCII hexidecimal representation of number stored at _TEXT:DI | ||
| 349 | ; | ||
| 350 | ; used: none | ||
| 351 | ; | ||
| 352 | ; stack: | ||
| 353 | ; | ||
| 354 | ;****************************************************************************** | ||
| 355 | ; | ||
| 356 | b2asc16 proc near | ||
| 357 | |||
| 358 | push ax | ||
| 359 | push bx | ||
| 360 | push cx | ||
| 361 | |||
| 362 | mov cx,4 | ||
| 363 | b2asc16_loop: | ||
| 364 | mov bl,ah | ||
| 365 | shr bl,4 | ||
| 366 | add bl,'0' | ||
| 367 | cmp bl,'9' | ||
| 368 | jbe b2asc16_skip | ||
| 369 | add bl,'A'-'9'-1 | ||
| 370 | b2asc16_skip: | ||
| 371 | mov ds:[di],bl | ||
| 372 | shl ax,4 | ||
| 373 | inc di | ||
| 374 | loop b2asc16_loop | ||
| 375 | |||
| 376 | pop cx | ||
| 377 | pop bx | ||
| 378 | pop ax | ||
| 379 | ret | ||
| 380 | |||
| 381 | b2asc16 endp | ||
| 382 | |||
| 383 | _TEXT ENDS | ||
| 384 | END | ||
| 385 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/EXTPOOL.ASM b/v4.0/src/MEMM/MEMM/EXTPOOL.ASM new file mode 100644 index 0000000..de7b492 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/EXTPOOL.ASM | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE EXTPOOL - MODULE to manage a pool of extended memory | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: EXTPOOL - Manage a pool of extended memory. | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Sep 1, 1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP (ISP) | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; Functional Description: | ||
| 28 | ; | ||
| 29 | ; "Fixit Orders" Crisis mode file. We need to ship data structures up hi. | ||
| 30 | ; So at init time we get a pool of extended memory and manage it for the | ||
| 31 | ; fixit routine. Services provided include initialise, allocate and | ||
| 32 | ; blkmov to the memory. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | .lfcond | ||
| 36 | .386p | ||
| 37 | |||
| 38 | page | ||
| 39 | ;****************************************************************************** | ||
| 40 | ; P U B L I C D E C L A R A T I O N S | ||
| 41 | ;****************************************************************************** | ||
| 42 | public pool_initialise | ||
| 43 | public get_buffer | ||
| 44 | |||
| 45 | page | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; L O C A L C O N S T A N T S | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; | ||
| 50 | |||
| 51 | ;****************************************************************************** | ||
| 52 | ; INCLUDE FILES | ||
| 53 | ;****************************************************************************** | ||
| 54 | include vdmseg.inc ; segment definitions | ||
| 55 | |||
| 56 | page | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; E X T E R N A L R E F E R E N C E S | ||
| 59 | ;****************************************************************************** | ||
| 60 | ; | ||
| 61 | ; | ||
| 62 | page | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; S E G M E N T D E F I N I T I O N | ||
| 65 | ;****************************************************************************** | ||
| 66 | |||
| 67 | ;************************************************************************* | ||
| 68 | ; | ||
| 69 | ; DATA | ||
| 70 | ; | ||
| 71 | ;************************************************************************* | ||
| 72 | |||
| 73 | LAST SEGMENT | ||
| 74 | |||
| 75 | ext_start dw 0000h ; start of the pool of extended memory | ||
| 76 | dw 0010h ; 24 bit address | ||
| 77 | |||
| 78 | ext_size dw 0 ; size | ||
| 79 | dw 0 ; | ||
| 80 | |||
| 81 | LAST ENDS | ||
| 82 | |||
| 83 | ;************************************************************************* | ||
| 84 | ; | ||
| 85 | ; CODE | ||
| 86 | ; | ||
| 87 | ;************************************************************************* | ||
| 88 | LAST SEGMENT | ||
| 89 | assume cs:LAST, DS:DGROUP, ES:DGROUP | ||
| 90 | |||
| 91 | |||
| 92 | ;****************************************************************************** | ||
| 93 | ;*** Pool Initialise *** Give this memory manager the memory it is to play ; | ||
| 94 | ; with. ; | ||
| 95 | ; ; | ||
| 96 | ; INPUTS: AX = start offset of the extended memory in K ; | ||
| 97 | ; CX = size of the memory ; | ||
| 98 | ; ; | ||
| 99 | ; OUTPUTS: None ; | ||
| 100 | ; ; | ||
| 101 | ; USES: None ; | ||
| 102 | ; ; | ||
| 103 | ; AUTHOR: ISP (ISP) Sep 1, 1988 ; | ||
| 104 | ; ; | ||
| 105 | ;*****************************************************************************; | ||
| 106 | |||
| 107 | Pool_Initialise proc near | ||
| 108 | ; | ||
| 109 | push dx | ||
| 110 | push cx | ||
| 111 | push ax | ||
| 112 | ; | ||
| 113 | push cx ; save size of memory | ||
| 114 | xor dx,dx | ||
| 115 | mov cx,1024 | ||
| 116 | mul cx ; dx:ax size in bytes offset from 1M | ||
| 117 | ; | ||
| 118 | add ax,cs:[ext_start] ; add it to 1M | ||
| 119 | adc dx,cs:[ext_start+2] ; | ||
| 120 | ; | ||
| 121 | mov cs:[ext_start],ax ; | ||
| 122 | mov cs:[ext_start+2],dx ; | ||
| 123 | ; | ||
| 124 | pop ax ; get size into ax | ||
| 125 | xor dx,dx ; | ||
| 126 | mul cx | ||
| 127 | ; | ||
| 128 | mov cs:[ext_size],ax | ||
| 129 | mov cs:[ext_size+2],dx | ||
| 130 | ; | ||
| 131 | pop ax | ||
| 132 | pop cx | ||
| 133 | pop dx | ||
| 134 | ; | ||
| 135 | ret | ||
| 136 | ; | ||
| 137 | Pool_Initialise endp | ||
| 138 | |||
| 139 | |||
| 140 | |||
| 141 | ;****************************************************************************** | ||
| 142 | ;***Get buffer*** Give some poor beggar the memory he is asking for ; | ||
| 143 | ; ; | ||
| 144 | ; INPUTS: cx = size of buffer required in bytes ; | ||
| 145 | ; ; | ||
| 146 | ; OUTPUTS: DX:AX = address of buffer ; | ||
| 147 | ; cx = size allocated | ||
| 148 | ; ; | ||
| 149 | ; USES: None ; | ||
| 150 | ; ; | ||
| 151 | ; AUTHOR: ISP (ISP) Sep 1, 1988 ; | ||
| 152 | ; ; | ||
| 153 | ;*****************************************************************************; | ||
| 154 | |||
| 155 | Get_Buffer proc near | ||
| 156 | ; | ||
| 157 | ; | ||
| 158 | ; assume that the memory is present, put start address in dx:ax | ||
| 159 | ; | ||
| 160 | mov dx,cs:[ext_start+2] | ||
| 161 | mov ax,cs:[ext_start] | ||
| 162 | ; | ||
| 163 | ; then proceed to determine if it really exists | ||
| 164 | ; | ||
| 165 | push eax | ||
| 166 | xor eax,eax | ||
| 167 | mov ax,cx | ||
| 168 | cmp eax, dword ptr cs:[ext_size] | ||
| 169 | ja no_mem | ||
| 170 | ; | ||
| 171 | ; it does exist, adjust the size and the start address | ||
| 172 | ; | ||
| 173 | sub dword ptr cs:[ext_size],eax | ||
| 174 | add dword ptr cs:[ext_start],eax | ||
| 175 | ; | ||
| 176 | pop eax | ||
| 177 | clc | ||
| 178 | ret | ||
| 179 | |||
| 180 | no_mem: | ||
| 181 | pop eax | ||
| 182 | stc | ||
| 183 | ret | ||
| 184 | Get_buffer endp | ||
| 185 | |||
| 186 | LAST ENDS | ||
| 187 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/I286.ASM b/v4.0/src/MEMM/MEMM/I286.ASM new file mode 100644 index 0000000..8eb2102 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/I286.ASM | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE i286.asm - Support Routines for protected mode system | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: i286.asm - Support Routines for protected mode system | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; 02/05/86 A added is286, is386 | ||
| 28 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 29 | ; 06/03/86 C added push/pop es to Init_GDT and changed Ring 0 | ||
| 30 | ; stack to STACK0 and STACK0_SIZE. | ||
| 31 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 32 | ; | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional Description: | ||
| 36 | ; | ||
| 37 | ; Anthony Short | ||
| 38 | ; 26th Dec 1985 | ||
| 39 | ; | ||
| 40 | ; DESCRIPTION | ||
| 41 | ; | ||
| 42 | ; These routines manage the various 286 memory management | ||
| 43 | ; tables and manipulate descriptors and selectors. | ||
| 44 | ; | ||
| 45 | ; The routines which deal with descriptors use the following | ||
| 46 | ; register usage conventions: | ||
| 47 | ; | ||
| 48 | ; BX - selector of required descriptor. The selector may | ||
| 49 | ; have RPL bits present, the routines ignore them. | ||
| 50 | ; | ||
| 51 | ; CX - SIZE IN BYTES of segment. NOTE: descriptors contain | ||
| 52 | ; limits, not sizes (limit = size - 1). Since everyone | ||
| 53 | ; else talks sizes, these routines do too, and do their | ||
| 54 | ; own conversion. | ||
| 55 | ; | ||
| 56 | ; DX - second selector when needed | ||
| 57 | ; | ||
| 58 | ; AH - access rights byte | ||
| 59 | ; | ||
| 60 | ; AL, DX - 24 bit physical address | ||
| 61 | ; | ||
| 62 | ; ES:0 - pointer to the desired descriptor table. | ||
| 63 | ; | ||
| 64 | ; All the routines which manipulate descriptors are callable | ||
| 65 | ; in both real and protected mode. | ||
| 66 | ; | ||
| 67 | ; In general all registers are preserved. | ||
| 68 | ; | ||
| 69 | ; The following routines are provided: | ||
| 70 | ; | ||
| 71 | ; SetDescInfo - set descriptor information | ||
| 72 | ; SetSegDesc - set segment descriptor information | ||
| 73 | ; | ||
| 74 | ; SegTo24 - convert segment number to 24 bit addr | ||
| 75 | ; SegOffTo24 - convert seg:offset to 24 bit addr | ||
| 76 | ; | ||
| 77 | ; InitGdt - set up parts of GDT which cannot easily | ||
| 78 | ; be initialised statically. | ||
| 79 | ; | ||
| 80 | ; WARNING This code is 286 specific, it will NOT run on an 8088. | ||
| 81 | ; | ||
| 82 | ;****************************************************************************** | ||
| 83 | .lfcond ; list false conditionals | ||
| 84 | .386p | ||
| 85 | |||
| 86 | |||
| 87 | include VDMseg.inc | ||
| 88 | include VDMsel.inc | ||
| 89 | include desc.inc | ||
| 90 | |||
| 91 | ;****************************************************************************** | ||
| 92 | ; E X T E R N A L R E F E R E N C E S | ||
| 93 | ;****************************************************************************** | ||
| 94 | GDT segment | ||
| 95 | extrn GDTLEN:abs | ||
| 96 | GDT ends | ||
| 97 | |||
| 98 | IDT segment | ||
| 99 | extrn IDTLEN:abs | ||
| 100 | IDT ends | ||
| 101 | |||
| 102 | TSS segment | ||
| 103 | extrn TSSLEN:abs | ||
| 104 | TSS ends | ||
| 105 | |||
| 106 | LAST SEGMENT | ||
| 107 | |||
| 108 | assume cs:LAST | ||
| 109 | |||
| 110 | ;** SetDescInfo - set descriptor information | ||
| 111 | ; | ||
| 112 | ; The limit field of a specified descriptor is set. | ||
| 113 | ; (limit = size - 1). | ||
| 114 | ; The base address of the specified descriptor is set. | ||
| 115 | ; The access field of the specified descriptor is set. | ||
| 116 | ; | ||
| 117 | ; ENTRY BX = selector | ||
| 118 | ; ES:0 = descriptor table to use | ||
| 119 | ; CX = limit | ||
| 120 | ; AL, DX = 24 bit base address | ||
| 121 | ; AH = access rights byte | ||
| 122 | ; EXIT None | ||
| 123 | ; USES Flags, other regs preserved | ||
| 124 | ; | ||
| 125 | ; WARNING This code only works on a 286. It can be called in | ||
| 126 | ; either mode. | ||
| 127 | |||
| 128 | public SetDescInfo | ||
| 129 | SetDescInfo proc near | ||
| 130 | push bx ; save selector | ||
| 131 | and bl,SEL_LOW_MASK | ||
| 132 | |||
| 133 | ; fill in the limit field | ||
| 134 | |||
| 135 | mov es:[bx],cx | ||
| 136 | |||
| 137 | ; fill in base address | ||
| 138 | |||
| 139 | mov es:[bx + 2],dx | ||
| 140 | mov es:[bx + 4],al | ||
| 141 | |||
| 142 | ; fill in access rights byte | ||
| 143 | |||
| 144 | mov es:[bx + 5],ah | ||
| 145 | pop bx | ||
| 146 | ret | ||
| 147 | SetDescInfo endp | ||
| 148 | |||
| 149 | |||
| 150 | ;** SetSegDesc - set segment descriptor information | ||
| 151 | ; | ||
| 152 | ; The limit field of a specified descriptor is set. | ||
| 153 | ; (limit = size - 1). | ||
| 154 | ; The base address of the specified descriptor is set. | ||
| 155 | ; The access field of the specified descriptor is set. | ||
| 156 | ; | ||
| 157 | ; ENTRY BX = selector | ||
| 158 | ; ES:0 = descriptor table to use | ||
| 159 | ; CX = size | ||
| 160 | ; AL, DX = 24 bit base address | ||
| 161 | ; AH = access rights byte | ||
| 162 | ; EXIT None | ||
| 163 | ; USES Flags, other regs preserved | ||
| 164 | ; | ||
| 165 | ; WARNING This code only works on a 286. It can be called in | ||
| 166 | ; either mode. | ||
| 167 | |||
| 168 | public SetSegDesc | ||
| 169 | SetSegDesc proc near | ||
| 170 | dec cx ; convert size to limit | ||
| 171 | call SetDescInfo ; set descriptor information | ||
| 172 | inc cx ; restore size | ||
| 173 | ret | ||
| 174 | SetSegDesc endp | ||
| 175 | |||
| 176 | |||
| 177 | ;** SegTo24 - convert segment to 24 bit physical address | ||
| 178 | ; | ||
| 179 | ; The real mode segment number is convert to a 24 bit addr | ||
| 180 | ; | ||
| 181 | ; ENTRY AX = segment | ||
| 182 | ; EXIT AL, DX = 24 bit physical address | ||
| 183 | ; USES AH, Flags, other regs preserved | ||
| 184 | ; | ||
| 185 | ; WARNING This code only works on a 286, it can be called in | ||
| 186 | ; either mode. | ||
| 187 | public SegTo24 | ||
| 188 | SegTo24 proc near | ||
| 189 | mov dl,ah | ||
| 190 | shr dl,4 ; DH = high byte of 24 bit addr | ||
| 191 | xchg ax,dx ; AH = high byte, DX = segment | ||
| 192 | shl dx,4 ; DX = low word of 24 bit addr | ||
| 193 | ret | ||
| 194 | SegTo24 endp | ||
| 195 | |||
| 196 | |||
| 197 | ;** SegOffTo24 - convert seg:off to 24 bit physical address | ||
| 198 | ; | ||
| 199 | ; The specified real mode segment:offset is converted to | ||
| 200 | ; a 24 bit physical address. | ||
| 201 | ; | ||
| 202 | ; ENTRY AX = segment | ||
| 203 | ; DX = offset | ||
| 204 | ; EXIT AL, DX = 24 bit physical address | ||
| 205 | ; USES AH, Flags, other regs preserved. | ||
| 206 | ; | ||
| 207 | ; WARNING This code only works on a 286. It can be called in | ||
| 208 | ; either mode. | ||
| 209 | |||
| 210 | public SegOffTo24 | ||
| 211 | SegOffTo24 proc near | ||
| 212 | push cx | ||
| 213 | |||
| 214 | ; Convert AX:DX into 24 bit addr in AL, DX | ||
| 215 | |||
| 216 | mov ch,ah | ||
| 217 | shl ax,4 | ||
| 218 | shr ch,4 ; CH = high byte | ||
| 219 | add dx,ax ; DX = low word | ||
| 220 | mov al,ch ; AL = high byte | ||
| 221 | adc al,0 ; propagate cy from low word | ||
| 222 | |||
| 223 | pop cx | ||
| 224 | ret | ||
| 225 | SegOffTo24 endp | ||
| 226 | |||
| 227 | |||
| 228 | page | ||
| 229 | ;****************************************************************************** | ||
| 230 | ; IS286 - return type of processor (286 vs. 8088/86). 386 returns 286. | ||
| 231 | ; This routine relies on the documented behaviour of the PUSH SP | ||
| 232 | ; instruction as executed on the various processors. This routine | ||
| 233 | ; may be called from any mode on any processor, provided a proper | ||
| 234 | ; stack exists. | ||
| 235 | ; | ||
| 236 | ; ENTRY: (none) | ||
| 237 | ; EXIT: ZF = 1 if 8088/86 | ||
| 238 | ; ZF = 0 if 286/386 | ||
| 239 | ; USED: flags | ||
| 240 | ; STACK: 6 bytes | ||
| 241 | ;------------------------------------------------------------------------------ | ||
| 242 | public Is286 | ||
| 243 | Is286 proc near | ||
| 244 | push bp | ||
| 245 | push sp | ||
| 246 | mov bp,sp | ||
| 247 | cmp bp,[bp] ; compare SP with saved SP | ||
| 248 | pop bp ; clean SP off stack | ||
| 249 | pop bp ; restore BP | ||
| 250 | ret ; *** RETURN *** | ||
| 251 | Is286 endp | ||
| 252 | page | ||
| 253 | ;****************************************************************************** | ||
| 254 | ; Is386 - return type of processor (386 vs. 8088/86/286). | ||
| 255 | ; This routine relies on Intel-approved code that takes advantage | ||
| 256 | ; of the documented behavior of the high nibble of the flag word | ||
| 257 | ; in the REAL MODE of the various processors. The MSB (bit 15) | ||
| 258 | ; is always a one on the 8086 and 8088 and a zero on the 286 and | ||
| 259 | ; 386. Bit 14 (NT flag) and bits 13/12 (IOPL bit field) are | ||
| 260 | ; always zero on the 286, but can be set on the 386. | ||
| 261 | ; | ||
| 262 | ; For future compatibility of this test, it is strongly recommended | ||
| 263 | ; that this specific instruction sequence be used. The exit codes | ||
| 264 | ; can of course be changed to fit a particular need. | ||
| 265 | ; | ||
| 266 | ; CALLABLE FROM REAL MODE ONLY - FAR ROUTINE | ||
| 267 | ; | ||
| 268 | ; ENTRY: (none) | ||
| 269 | ; EXIT: STC if 8088/86/286 | ||
| 270 | ; CLC if 386 | ||
| 271 | ; USED: none | ||
| 272 | ; STACK: 6 bytes | ||
| 273 | ;------------------------------------------------------------------------------ | ||
| 274 | public Is386 | ||
| 275 | Is386 proc FAR | ||
| 276 | push ax | ||
| 277 | pushf ; save entry flags | ||
| 278 | ; | ||
| 279 | xor ax,ax ; 0000 into AX | ||
| 280 | push ax | ||
| 281 | popf ; try to put that in the flags | ||
| 282 | pushf | ||
| 283 | pop ax ; look at what really went into flags | ||
| 284 | test ax,08000h ;Q: was high bit set ? | ||
| 285 | jnz IsNot386_exit ; Y: 8086/8088 | ||
| 286 | mov ax,07000h ; N: try to set the NT/IOPL bits | ||
| 287 | push ax | ||
| 288 | popf ; ... in the flags | ||
| 289 | pushf | ||
| 290 | pop ax ; look at actual flags | ||
| 291 | test ax,07000h ; Q: any high bits set ? | ||
| 292 | jz IsNot386_exit ; N: 80286 | ||
| 293 | ; Y: 80386 | ||
| 294 | Is386_exit: | ||
| 295 | popf ; restore flags | ||
| 296 | clc ; 386 | ||
| 297 | jmp short I386_exit ; and leave | ||
| 298 | |||
| 299 | IsNot386_exit: | ||
| 300 | popf ; restore flags | ||
| 301 | stc ; not a 386 | ||
| 302 | |||
| 303 | I386_exit: | ||
| 304 | pop ax | ||
| 305 | ret ; *** RETURN *** | ||
| 306 | |||
| 307 | Is386 endp | ||
| 308 | |||
| 309 | LAST ends | ||
| 310 | |||
| 311 | |||
| 312 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/I386.ASM b/v4.0/src/MEMM/MEMM/I386.ASM new file mode 100644 index 0000000..6065dbe --- /dev/null +++ b/v4.0/src/MEMM/MEMM/I386.ASM | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE i386.asm - Support Routines for protected mode system | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: i386.asm - Support Routines for protected mode system | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/21/86 0.02 Added clds just in case | ||
| 29 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; DESCRIPTION | ||
| 35 | ; | ||
| 36 | ; These routines manage the various 386 memory management | ||
| 37 | ; tables and manipulate descriptors and selectors. | ||
| 38 | ; | ||
| 39 | ; All the routines which manipulate descriptors are callable | ||
| 40 | ; in both real and protected mode. | ||
| 41 | ; | ||
| 42 | ; In general all registers are preserved. | ||
| 43 | ; | ||
| 44 | ; The following routines are provided: | ||
| 45 | ; | ||
| 46 | ; SetPageEntry - set up an entry in a Page Directory on Page | ||
| 47 | ; Table. | ||
| 48 | ; | ||
| 49 | ; GetPageEntry - retrieve a page dir/page table entry. | ||
| 50 | ; | ||
| 51 | ; InitPages - initialize page directory and page table. | ||
| 52 | ; | ||
| 53 | ; PageDirOff - convert 32 bit addr to page dir entry offset | ||
| 54 | ; | ||
| 55 | ; PageTableOff - convert 32 bit addr to page table entry offset | ||
| 56 | ; | ||
| 57 | ; WARNING This code is 386 specific, it will NOT run on an 8088. | ||
| 58 | ; | ||
| 59 | ;****************************************************************************** | ||
| 60 | .lfcond ; list false conditionals | ||
| 61 | .386p | ||
| 62 | ; | ||
| 63 | include VDMseg.inc | ||
| 64 | include VDMsel.inc | ||
| 65 | include desc.inc | ||
| 66 | include page.inc | ||
| 67 | |||
| 68 | ;****************************************************************************** | ||
| 69 | ; E X T E R N A L S | ||
| 70 | ;****************************************************************************** | ||
| 71 | LAST SEGMENT | ||
| 72 | extrn SegTo24:near | ||
| 73 | LAST ENDS | ||
| 74 | |||
| 75 | |||
| 76 | ;****************************************************************************** | ||
| 77 | ; S E G M E N T D E F I N I T I O N S | ||
| 78 | ;****************************************************************************** | ||
| 79 | LAST SEGMENT | ||
| 80 | |||
| 81 | assume cs:LAST,ds:DGROUP,es:DGROUP | ||
| 82 | |||
| 83 | ;** SetGateDesc - set up Gate Descriptor entry | ||
| 84 | ; | ||
| 85 | ; | ||
| 86 | ; ENTRY DX,AX = 32 bit offset of target routine | ||
| 87 | ; CX = target code segment selector | ||
| 88 | ; ES:[DI] = points to table entry | ||
| 89 | ; BL = access bits | ||
| 90 | ; EXIT descriptor set. | ||
| 91 | ; USES Flags, other regs preserved | ||
| 92 | ; | ||
| 93 | ; WARNING This code only works on a 386. It can be called in | ||
| 94 | ; either mode. | ||
| 95 | |||
| 96 | public SetGateDesc | ||
| 97 | SetGateDesc proc near | ||
| 98 | ; | ||
| 99 | push ax | ||
| 100 | push di | ||
| 101 | ; | ||
| 102 | cld ; stings foward | ||
| 103 | ; | ||
| 104 | stosw ; store low word of offset | ||
| 105 | mov ax,cx | ||
| 106 | stosw ; store selector | ||
| 107 | mov al,0 | ||
| 108 | mov ah,bl | ||
| 109 | stosw ; store access rights | ||
| 110 | mov ax,dx | ||
| 111 | stosw ; store high word of offset | ||
| 112 | ; | ||
| 113 | pop di | ||
| 114 | pop ax | ||
| 115 | ret | ||
| 116 | SetGateDesc endp | ||
| 117 | |||
| 118 | |||
| 119 | ;** SetPageEntry - set up entry in Page Directory or Page Table | ||
| 120 | ; | ||
| 121 | ; | ||
| 122 | ; ENTRY DX,AX = 32 bit address of page or page table | ||
| 123 | ; ES:[DI] = page directory or table entry to set | ||
| 124 | ; BX = access/status bits ( bits 0 - 11 ) | ||
| 125 | ; EXIT ES:[DI] = next page directory or table entry | ||
| 126 | ; USES Flags, other regs preserved | ||
| 127 | ; | ||
| 128 | ; WARNING This code only works on a 386. It can be called in | ||
| 129 | ; either mode. | ||
| 130 | |||
| 131 | public SetPageEntry | ||
| 132 | SetPageEntry proc near | ||
| 133 | ; | ||
| 134 | push ax | ||
| 135 | ; | ||
| 136 | cld ; strings foward | ||
| 137 | ; | ||
| 138 | and bx,0FFFh ; turn off any bits in address range | ||
| 139 | or ax,bx ; mov status bits into AX | ||
| 140 | stosw ; store status and addr bits 12 - 15 | ||
| 141 | mov ax,dx ; AX = addr bits 16-31 | ||
| 142 | stosw ; store addr bits 16-31 | ||
| 143 | ; | ||
| 144 | pop ax | ||
| 145 | ret | ||
| 146 | SetPageEntry endp | ||
| 147 | |||
| 148 | |||
| 149 | ;** GetPageEntry - up entry in Page Directory or Page Table | ||
| 150 | ; | ||
| 151 | ; ENTRY ES:[DI] = page directory or table entry | ||
| 152 | ; EXIT DX,AX = 32 bit address of page or page table | ||
| 153 | ; BX = access/status bits (bits 0 - 11). | ||
| 154 | ; USES Flags, other regs preserved | ||
| 155 | ; | ||
| 156 | ; WARNING This code only works on a 386. It can be called in | ||
| 157 | ; either mode. | ||
| 158 | |||
| 159 | public GetPageEntry | ||
| 160 | GetPageEntry proc near | ||
| 161 | ; | ||
| 162 | mov ax,ES:[DI] ; AX = low word of entry | ||
| 163 | mov bx,ax ; get access/status rights bits | ||
| 164 | and bx,00FFFh ; turn off address bits | ||
| 165 | ; | ||
| 166 | and ax,0F000h ; turn off status bits | ||
| 167 | mov dx,ES:[DI+2] ; get high word of addr | ||
| 168 | ; | ||
| 169 | ret | ||
| 170 | GetPageEntry endp | ||
| 171 | |||
| 172 | |||
| 173 | ;** PageDirOff - convert 32 bit linear address to page directory offset | ||
| 174 | ; | ||
| 175 | ; | ||
| 176 | ; ENTRY EAX = 32 bit linear address | ||
| 177 | ; EXIT DI = offset in page dir to appropriate entry | ||
| 178 | ; USES Flags, other regs preserved | ||
| 179 | ; | ||
| 180 | ; WARNING This code only works on a 386. It can be called in | ||
| 181 | ; either mode. | ||
| 182 | |||
| 183 | public PageDirOff | ||
| 184 | PageDirOff proc near | ||
| 185 | ; | ||
| 186 | db 66h | ||
| 187 | push bx ; push EBX | ||
| 188 | |||
| 189 | db 66h | ||
| 190 | mov bx,ax ; EBX = EAX | ||
| 191 | |||
| 192 | db 66h | ||
| 193 | shr bx,22 ; EBX[0:9] = EBX[22:31] = high 10 bits | ||
| 194 | shl bx,2 ; *4 for dword indexing into table | ||
| 195 | |||
| 196 | mov di,bx ; DI = dir offset | ||
| 197 | |||
| 198 | db 66h | ||
| 199 | pop bx ; pop EBX | ||
| 200 | ; | ||
| 201 | ret | ||
| 202 | PageDirOff endp | ||
| 203 | |||
| 204 | |||
| 205 | ;** PageTableOff - convert 32 bit linear address to page table offset | ||
| 206 | ; | ||
| 207 | ; | ||
| 208 | ; ENTRY EAX = 32 bit linear address | ||
| 209 | ; EXIT DI = offset in page table to appropriate entry | ||
| 210 | ; USES Flags, other regs preserved | ||
| 211 | ; | ||
| 212 | ; WARNING This code only works on a 386. It can be called in | ||
| 213 | ; either mode. | ||
| 214 | |||
| 215 | public PageTableOff | ||
| 216 | PageTableOff proc near | ||
| 217 | ; | ||
| 218 | db 66h | ||
| 219 | push bx ; push EBX | ||
| 220 | |||
| 221 | db 66h | ||
| 222 | mov bx,ax ; mov EBX,EAX | ||
| 223 | |||
| 224 | db 66h | ||
| 225 | shr bx,12 ; EBX[0:9] = EBX[12:21] = middle 10 bits | ||
| 226 | and bx,3FFh ; only EBX[0:9] | ||
| 227 | shl bx,2 ; *4 for dword indexing into table | ||
| 228 | |||
| 229 | mov di,bx ; DI has table offset | ||
| 230 | |||
| 231 | db 66h | ||
| 232 | pop bx ; pop EBX | ||
| 233 | ; | ||
| 234 | ret | ||
| 235 | PageTableOff endp | ||
| 236 | |||
| 237 | |||
| 238 | LAST ends | ||
| 239 | |||
| 240 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/INIT.ASM b/v4.0/src/MEMM/MEMM/INIT.ASM new file mode 100644 index 0000000..44ab1c7 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INIT.ASM | |||
| @@ -0,0 +1,1123 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE INIT - initialization code for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: INIT - initialization code for MEMM | ||
| 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 | ; 05/24/86 Original | ||
| 27 | ; 06/18/86 0.01 Added AUTO as a valid config line parameter. | ||
| 28 | ; 06/25/86 0.02 Added call to debug init. | ||
| 29 | ; 06/27/86 0.02 Check for Mx length = 2 and only 2 | ||
| 30 | ; 06/28/86 0.02 Change name from MEMM386 to MEMM | ||
| 31 | ; 06/29/86 0.02 Size > 8192 were used instead of converted | ||
| 32 | ; to 256 | ||
| 33 | ; 07/03/86 0.04 Added TEXT_Seg | ||
| 34 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 35 | ; 07/06/86 0.04 moved init messages to LAST | ||
| 36 | ; 07/10/86 0.05 added int15 patch and int67 patch here | ||
| 37 | ; 07/20/88 removed debugger codes (pc) | ||
| 38 | ; 07/29/88 removed ON/OFF/AUTO support | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; Functional Description: | ||
| 42 | ; This module allocates the pool of extended memory to be used for | ||
| 43 | ; expanded memory, then call routines to initialize the data structures | ||
| 44 | ; for EMM and VDM. | ||
| 45 | ; | ||
| 46 | ;****************************************************************************** | ||
| 47 | .lfcond | ||
| 48 | .386p | ||
| 49 | page | ||
| 50 | ;****************************************************************************** | ||
| 51 | ; P U B L I C D E C L A R A T I O N S | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; | ||
| 54 | public Init_MEMM386 | ||
| 55 | |||
| 56 | public pool_size | ||
| 57 | public msg_flag | ||
| 58 | public Active_Status | ||
| 59 | public Auto_Mode | ||
| 60 | public dos_version | ||
| 61 | public TEXT_Seg | ||
| 62 | public STACK_Seg | ||
| 63 | public GDT_Seg | ||
| 64 | public IDT_Seg | ||
| 65 | public TSS_Seg | ||
| 66 | public driver_end | ||
| 67 | public powr10 | ||
| 68 | |||
| 69 | |||
| 70 | page | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; L O C A L C O N S T A N T S | ||
| 73 | ;****************************************************************************** | ||
| 74 | ; | ||
| 75 | include vdmseg.inc | ||
| 76 | include vdmsel.inc ; for Deb386 Init | ||
| 77 | include desc.inc ; " " " | ||
| 78 | include emm386.inc | ||
| 79 | include driver.equ | ||
| 80 | include driver.str | ||
| 81 | include ascii_sm.equ | ||
| 82 | ; | ||
| 83 | ; maximum value for SIZE parameter | ||
| 84 | ; | ||
| 85 | MAX_SIZE equ 32 * 1024 ; 32K => 32Meg | ||
| 86 | |||
| 87 | ; | ||
| 88 | MS_DOS equ 21h | ||
| 89 | PRINT_STRING equ 09h | ||
| 90 | GET_VERSION equ 30h | ||
| 91 | ; | ||
| 92 | FALSE equ 0 | ||
| 93 | TRUE equ not FALSE | ||
| 94 | DOS3X_ADJ equ 1 ; DOS 3.x base memory adjustment | ||
| 95 | |||
| 96 | ; | ||
| 97 | ; macro for printing messages located in LAST segment | ||
| 98 | ; ENTRY: DX = offset LAST:message | ||
| 99 | ; | ||
| 100 | PRINT_MSG macro | ||
| 101 | push ds | ||
| 102 | push seg LAST | ||
| 103 | pop ds ; ds = LAST | ||
| 104 | mov ah,PRINT_STRING | ||
| 105 | int MS_DOS ; output init message | ||
| 106 | pop ds | ||
| 107 | ENDM | ||
| 108 | |||
| 109 | |||
| 110 | ;****************************************************************************** | ||
| 111 | ; E X T E R N A L R E F E R E N C E S | ||
| 112 | ;****************************************************************************** | ||
| 113 | ; | ||
| 114 | ; | ||
| 115 | _DATA segment | ||
| 116 | |||
| 117 | extrn PF_Base:word | ||
| 118 | ; extrn himem_use:byte ;* this is defined in oemproc.asm since it | ||
| 119 | ; deals with memory so oem dependent | ||
| 120 | extrn ext_size:word ; size of extended memory allocated | ||
| 121 | extrn sys_size:word ; size of system memory allocated | ||
| 122 | |||
| 123 | _DATA ends | ||
| 124 | |||
| 125 | ABS0 segment use16 at 0 | ||
| 126 | org 4*15h ; int 15h vector | ||
| 127 | i15_vector dw 0 | ||
| 128 | dw 0 | ||
| 129 | |||
| 130 | org 4*67h ; int 67h vector | ||
| 131 | i67_vector dw 0 | ||
| 132 | dw 0 | ||
| 133 | ABS0 ends | ||
| 134 | |||
| 135 | ; | ||
| 136 | R_CODE segment | ||
| 137 | extrn i15_Entry:near ; int15h patch code | ||
| 138 | extrn EMM_rEntry:near ; int67h patch code | ||
| 139 | extrn i15_Old:word ; old int15 vector | ||
| 140 | R_CODE ends | ||
| 141 | |||
| 142 | ; | ||
| 143 | _TEXT segment | ||
| 144 | |||
| 145 | extrn Inst_chk_f:far ; check for MEMM already installed | ||
| 146 | extrn FarGoVirtual:far ; go to virtual mode | ||
| 147 | extrn get_token:near ; get token from command line | ||
| 148 | |||
| 149 | _TEXT ends | ||
| 150 | ; | ||
| 151 | LAST segment | ||
| 152 | |||
| 153 | extrn VerifyMachine:near | ||
| 154 | extrn InitMess:byte | ||
| 155 | extrn InstallMess:byte | ||
| 156 | extrn ISizeMess:byte | ||
| 157 | extrn ExtSizeMess:byte | ||
| 158 | extrn SysSizeMess:byte | ||
| 159 | extrn PFBAMess:byte | ||
| 160 | extrn ActiveMess:byte | ||
| 161 | extrn InactiveMess:byte | ||
| 162 | extrn AutoMess:byte | ||
| 163 | extrn InvParm:byte | ||
| 164 | extrn InvPFBA:byte | ||
| 165 | extrn InvMRA:byte | ||
| 166 | extrn Adj_Size:byte | ||
| 167 | extrn InsfMem:byte | ||
| 168 | extrn Incorrect_DOS:byte | ||
| 169 | extrn Incorrect_PRT:byte | ||
| 170 | extrn Already_Inst:byte | ||
| 171 | extrn No_PF_Avail:byte | ||
| 172 | extrn PFWarning:byte | ||
| 173 | |||
| 174 | extrn Is386:far ; check for 386 | ||
| 175 | extrn EMM_Init:near ; initialization for EMM data structs | ||
| 176 | extrn AllocMem:near ; allocate extended memory routine | ||
| 177 | extrn InitTab:near ; OEM init code for tables | ||
| 178 | extrn VDM_Init:near ; initialize VDM | ||
| 179 | extrn DeallocMem:near ; deallocate hi/extended memory routine | ||
| 180 | |||
| 181 | extrn find_phys_pages:near ; find the mappable pages in 0-1M range | ||
| 182 | extrn exclude_segments:near ; exclude segments within a range | ||
| 183 | extrn estb_mach_state:near ; establish machine environment | ||
| 184 | |||
| 185 | LAST ends | ||
| 186 | |||
| 187 | page | ||
| 188 | ;****************************************************************************** | ||
| 189 | ; S E G M E N T D E F I N I T I O N | ||
| 190 | ;****************************************************************************** | ||
| 191 | |||
| 192 | page | ||
| 193 | ;****************************************************************************** | ||
| 194 | ; Data segment | ||
| 195 | ;****************************************************************************** | ||
| 196 | _DATA segment | ||
| 197 | ; | ||
| 198 | dos_version db 0h ; MS-DOS version | ||
| 199 | pool_size dw 0 ; size of EMM Pages Pool in kbytes | ||
| 200 | msg_flag dw 0 ; Message flag byte | ||
| 201 | |||
| 202 | driver_end dw 0 ; end of driver -> driver brk address | ||
| 203 | dw seg LAST | ||
| 204 | powr10 dw 1,10,100,1000,10000 | ||
| 205 | max_arg_len equ 11 ; maximum length of argument on cmd line | ||
| 206 | arg_str db max_arg_len+1 dup(0) | ||
| 207 | ; | ||
| 208 | ; Active_Status is used to signal the termination condition for the | ||
| 209 | ; driver. After the driver installs, Active_Status holds the | ||
| 210 | ; current status (ON or OFF). | ||
| 211 | ; Auto_Mode is set when MEMM is running in AUTO mode. | ||
| 212 | ; | ||
| 213 | Active_Status db 0FFh ; 0 => OFF , non-zero => ON | ||
| 214 | Auto_Mode db 0h ; non-zero => auto mode | ||
| 215 | |||
| 216 | ; | ||
| 217 | ; The following pointers are segment addresses for various segments | ||
| 218 | ; | ||
| 219 | TEXT_Seg dw seg _TEXT ; current segment for _TEXT | ||
| 220 | STACK_Seg dw seg STACK ; current segment for STACK | ||
| 221 | GDT_Seg dw seg GDT ; current segment for GDT | ||
| 222 | IDT_Seg dw seg IDT ; current segment for IDT | ||
| 223 | TSS_Seg dw seg TSS ; current segment for TSS | ||
| 224 | |||
| 225 | _DATA ends | ||
| 226 | |||
| 227 | |||
| 228 | ;****************************************************************************** | ||
| 229 | ; | ||
| 230 | ; Code Segments | ||
| 231 | ; | ||
| 232 | ;****************************************************************************** | ||
| 233 | ; | ||
| 234 | _TEXT segment | ||
| 235 | assume cs:_TEXT | ||
| 236 | |||
| 237 | |||
| 238 | ;************************************************************************* | ||
| 239 | ; | ||
| 240 | ; get_token_far call get_token which must be near since it is | ||
| 241 | ; also part of a .COM file | ||
| 242 | ; | ||
| 243 | ;************************************************************************* | ||
| 244 | get_token_far proc far | ||
| 245 | call get_token | ||
| 246 | ret | ||
| 247 | get_token_far endp | ||
| 248 | _TEXT ends | ||
| 249 | |||
| 250 | LAST segment | ||
| 251 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 252 | |||
| 253 | page | ||
| 254 | ;****************************************************************************** | ||
| 255 | ; Init - Initialization routine for MEMM. | ||
| 256 | ; | ||
| 257 | ; ENTRY: DS:BX pts to INIT request header. | ||
| 258 | ; | ||
| 259 | ; EXIT: AX = INIT status for request header | ||
| 260 | ; if NO errors : | ||
| 261 | ; MEMM initialized. | ||
| 262 | ; if [ON] parameter specified on command line | ||
| 263 | ; exit in Virtual mode and MEMM active. | ||
| 264 | ; else ( [OFF] parameter specified ) | ||
| 265 | ; exit in Real mode and MEMM inactive. | ||
| 266 | ; if errors: | ||
| 267 | ; Real Mode | ||
| 268 | ; USED: none | ||
| 269 | ; | ||
| 270 | ;****************************************************************************** | ||
| 271 | Init_MEMM386 proc far | ||
| 272 | push bx ; BP+10 | ||
| 273 | push dx ; BP+8 | ||
| 274 | push bp ; BP+6 | ||
| 275 | push di ; BP+4 | ||
| 276 | push ds ; BP+2 | ||
| 277 | push es ; BP+0 | ||
| 278 | mov bp,sp | ||
| 279 | ; | ||
| 280 | ; set up DS = DGROUP and ES:BX to request header | ||
| 281 | ; | ||
| 282 | push ds | ||
| 283 | pop es ; ES:BX pts to req hdr | ||
| 284 | mov ax,seg DGROUP | ||
| 285 | mov ds,ax ; DS = DGROUP | ||
| 286 | |||
| 287 | ; | ||
| 288 | ; initialize break address to not install | ||
| 289 | ; | ||
| 290 | mov word ptr ES:[bx.BRK_OFF],0000 ; set it | ||
| 291 | mov ax,seg R_CODE ; get brk addr segment | ||
| 292 | inc ax ; reserve dos link pointer | ||
| 293 | mov ES:[bx.BRK_SEG],ax ; break addr = cs - don't install | ||
| 294 | mov byte ptr es:[bx.NUM_UNITS],0 ; 0 - don't install | ||
| 295 | ; | ||
| 296 | ; verify that MEMM is not already installed | ||
| 297 | ; | ||
| 298 | call Inst_chk_f | ||
| 299 | or ax,ax ; q: already installed? | ||
| 300 | jz chk_pt ; n: go check processor type | ||
| 301 | or [msg_flag],INS_ERR_MSG ; y: error | ||
| 302 | jmp IE_exit ; quit | ||
| 303 | ; | ||
| 304 | ; verify processor type | ||
| 305 | ; | ||
| 306 | chk_pt: | ||
| 307 | call Is386 ;Q: is this a 386 ? | ||
| 308 | jnz inc_prc ; N: no, set error | ||
| 309 | ; Y: check machine type | ||
| 310 | ; | ||
| 311 | ; verify machine type | ||
| 312 | ; | ||
| 313 | chk_mt: | ||
| 314 | stc ; Indicate this is verify from INIT | ||
| 315 | call VerifyMachine ;Q: is this a good machine to run on? | ||
| 316 | jnc chk_dos ; y: ok so far. go check dos version | ||
| 317 | inc_prc: | ||
| 318 | or [msg_flag],INC_PRC_MSG ; n: incorrect processor type | ||
| 319 | jmp IE_exit ; quit | ||
| 320 | ; | ||
| 321 | ; get DOS version - accept >= 3.1 | ||
| 322 | ; | ||
| 323 | chk_dos: | ||
| 324 | push bx | ||
| 325 | mov ah,GET_VERSION | ||
| 326 | int MS_DOS ; get dos version # | ||
| 327 | mov [dos_version],al ; save it. | ||
| 328 | pop bx | ||
| 329 | cmp ax,4 ;Q: DOS 4.00 | ||
| 330 | je IE_parse ; Y: OK - continue install | ||
| 331 | cmp al,3 ;Q: DOS 3.xx ? | ||
| 332 | jl IE_dos_err ; N: return error | ||
| 333 | cmp ah,10 ;Q: current DOS >= 3.10 ? | ||
| 334 | jae IE_parse ; Y: OK - continue install | ||
| 335 | IE_dos_err: | ||
| 336 | or [msg_flag],INC_DOS_MSG ; N: set error and exit | ||
| 337 | jmp IE_exit | ||
| 338 | ; | ||
| 339 | ; parse command line for | ||
| 340 | ; (1) requested size for expanded memory | ||
| 341 | ; (2) page frame base address | ||
| 342 | ; (3) I/O addresses for board emulations | ||
| 343 | ; (4) Driver exit mode (virtual or real) | ||
| 344 | ; | ||
| 345 | IE_parse: | ||
| 346 | les di,ES:[bx.ARG_PTR] ; ES:DI pts to config.sys command | ||
| 347 | ; line parameters | ||
| 348 | call parser ; parse the parameters | ||
| 349 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 350 | jz IE_mach_state ; N: go to establish machine state | ||
| 351 | jmp IE_exit ; Y: exit with error | ||
| 352 | |||
| 353 | IE_mach_state: | ||
| 354 | ; | ||
| 355 | push ds | ||
| 356 | pop es ; ES:DGROUP | ||
| 357 | ; | ||
| 358 | call estb_mach_state ; since we are an environment, we need | ||
| 359 | ; to find the state we exist in right | ||
| 360 | ; now and maintain it. | ||
| 361 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 362 | jz IE_find_phys ; N:go to find physical pages | ||
| 363 | jmp IE_exit ; Y: exit with error | ||
| 364 | ; | ||
| 365 | IE_find_phys: | ||
| 366 | call find_phys_pages ; find mappable physical pages | ||
| 367 | ; and page frame | ||
| 368 | test [msg_flag],KILLER_MSG ;Q: any killer messages | ||
| 369 | jz IE_alloc ; N: Go to find and allocate log. pages | ||
| 370 | jmp IE_exit ; Y: exit with error | ||
| 371 | ; | ||
| 372 | ; find and allocate logical emm pages | ||
| 373 | ; | ||
| 374 | IE_alloc: | ||
| 375 | call AllocMem | ||
| 376 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 377 | jz IE_InitEMM ; N: init EMM | ||
| 378 | jmp IE_exit ; Y: exit | ||
| 379 | ; | ||
| 380 | ; init EMM data | ||
| 381 | ; | ||
| 382 | IE_InitEMM: | ||
| 383 | |||
| 384 | call EMM_Init | ||
| 385 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 386 | jz IE_InitVDM ; N: init VDM | ||
| 387 | jmp IE_exit ; Y: exit | ||
| 388 | ; | ||
| 389 | ; init VDM - GDT,IDT,TSS,Page Tables | ||
| 390 | ; | ||
| 391 | IE_InitVDM: | ||
| 392 | call VDM_Init | ||
| 393 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 394 | jz IE_InitTAB ; N: init TABLES | ||
| 395 | jmp IE_exit ; Y: exit | ||
| 396 | ; | ||
| 397 | ; set up segment pointers to Tables & OEM table init | ||
| 398 | ; | ||
| 399 | IE_InitTAB: | ||
| 400 | call InitTab | ||
| 401 | jnc IE_InitT_Good ;Q: any memory allocation error? | ||
| 402 | or [msg_flag],MEM_ERR_MSG ; Y: Some serious memory error | ||
| 403 | IE_InitT_Good: | ||
| 404 | test [msg_flag],KILLER_MSG ;Q: any killer messages? | ||
| 405 | jz IE_chkbase ; N: check base memory left | ||
| 406 | jmp IE_exit ; Y: exit | ||
| 407 | ; | ||
| 408 | ; Verify that we will have at least 64k of base memory after MEMM | ||
| 409 | ; is loaded | ||
| 410 | ; | ||
| 411 | IE_chkbase: | ||
| 412 | int 12h ; get base memory size | ||
| 413 | push ax ; save it | ||
| 414 | mov ax,[driver_end] ; get offset of end of MEMM resident | ||
| 415 | add ax,15 ; convert to paragraphs | ||
| 416 | shr ax,4 | ||
| 417 | add ax,[driver_end+2] ; add in segment of brk address | ||
| 418 | add ax,63 ; round up to kbytes (64 paras per K) | ||
| 419 | shr ax,6 ; AX = kbytes to end of MEMM resident | ||
| 420 | add ax,DOS3X_ADJ+64 ; add in dos 3.xx adjustment and 64k | ||
| 421 | pop dx ; get base memory back | ||
| 422 | cmp dx,ax ; q: do we have enough? | ||
| 423 | jae IE_setbrk ; y: continue | ||
| 424 | or [msg_flag],MEM_ERR_MSG ; n: set memory error | ||
| 425 | jmp IE_exit ; and exit | ||
| 426 | |||
| 427 | ; | ||
| 428 | ; set driver break addr in Init Request Header | ||
| 429 | ; | ||
| 430 | IE_setbrk: | ||
| 431 | mov bx,[bp+2] ; get entry DS from stack | ||
| 432 | mov es,bx | ||
| 433 | mov bx,[bp+10] ; ES:BX pts to req hdr | ||
| 434 | mov ax,[driver_end] ; get brk addr offset | ||
| 435 | mov ES:[bx.BRK_OFF],ax ; set it | ||
| 436 | mov ax,[driver_end+2] ; get brk addr segment | ||
| 437 | mov ES:[bx.BRK_SEG],ax ; set it | ||
| 438 | ; | ||
| 439 | ; check exit status of VDM/MEMM (now with lim 4.0) exit must be ON | ||
| 440 | ; | ||
| 441 | ; cmp [Auto_Mode],0 ;Q: exit in Auto mode ? | ||
| 442 | ; je IE_chkOFF ; N: then continue | ||
| 443 | ; mov [Active_Status],0 ; Y: exit in OFF state | ||
| 444 | ;IE_chkOFF: | ||
| 445 | ; cmp [Active_Status],0 ;Q: exit in real mode - OFF | ||
| 446 | ; je IE_Exit ; Y: continue | ||
| 447 | |||
| 448 | ; Initialize DEBX_GSEL GDT Selector and Deb386 | ||
| 449 | ; | ||
| 450 | push ds | ||
| 451 | push es | ||
| 452 | push ax | ||
| 453 | push bx | ||
| 454 | push cx | ||
| 455 | push si | ||
| 456 | push di | ||
| 457 | |||
| 458 | push [IDT_Seg] | ||
| 459 | pop es ; ES:DI <-- IDT | ||
| 460 | push [GDT_Seg] | ||
| 461 | pop ds ; DS:SI <-- GDT | ||
| 462 | mov bx, DEBX_GSEL | ||
| 463 | and bl, SEL_LOW_MASK | ||
| 464 | mov word ptr [bx], 1800h ; Limit = 20M | ||
| 465 | mov word ptr [bx + 2], 0 | ||
| 466 | mov byte ptr [bx + 4], 0 ; Base = 0 | ||
| 467 | mov byte ptr [bx + 5], D_DATA0 ; Ring 0 Data | ||
| 468 | mov byte ptr [bx + 6], 80h ; Page Granularity | ||
| 469 | |||
| 470 | mov ax, 4400h ; Initialize Deb386 | ||
| 471 | mov bx, DEBX_GSEL ; BIG selector for all addresses | ||
| 472 | mov cx, DEB1_GSEL ; start of 5 working Selector | ||
| 473 | xor si, si | ||
| 474 | xor di, di | ||
| 475 | int 68h | ||
| 476 | |||
| 477 | pop di | ||
| 478 | pop si | ||
| 479 | pop cx | ||
| 480 | pop bx | ||
| 481 | pop ax | ||
| 482 | pop es | ||
| 483 | pop ds | ||
| 484 | |||
| 485 | call FarGoVirtual ; N: go into virtual mode | ||
| 486 | |||
| 487 | ; | ||
| 488 | ; exit - display status messages and set exit status | ||
| 489 | ; | ||
| 490 | IE_exit: | ||
| 491 | ; | ||
| 492 | ; display signon message first | ||
| 493 | ; | ||
| 494 | mov dx,offset LAST:InitMess | ||
| 495 | PRINT_MSG | ||
| 496 | ; | ||
| 497 | ; check for messages to display | ||
| 498 | ; | ||
| 499 | IE_Install: | ||
| 500 | mov cx,MAX_MSG ; number of potential msgs | ||
| 501 | mov si,offset msg_tbl ; table of messages | ||
| 502 | m_loop: | ||
| 503 | test [msg_flag],01 ; q:is this one set? | ||
| 504 | jz m_inc_ptr ; n: increment table pointer | ||
| 505 | mov dx,cs:[si] ; y: display message | ||
| 506 | PRINT_MSG | ||
| 507 | cmp cx,KILL_MSG ; q: is this one a killer? | ||
| 508 | jbe m_inc_ptr ; n: continue | ||
| 509 | jmp IE_not_installed ; y: don't install | ||
| 510 | m_inc_ptr: | ||
| 511 | inc si ; increment msg table ptr | ||
| 512 | inc si | ||
| 513 | shr [msg_flag],1 ; look for next flag | ||
| 514 | loop m_loop | ||
| 515 | ; | ||
| 516 | mov ax,[pool_size] ; size of EMM page pool in Kbytes | ||
| 517 | mov di,offset LAST:ISizeMess; store decimal size in ASCII here. | ||
| 518 | call b2asc10 ; convert to ASCII... | ||
| 519 | ; | ||
| 520 | mov ax,[ext_size] | ||
| 521 | IFNDEF NOHIMEM | ||
| 522 | add ax,[hi_size] | ||
| 523 | endif | ||
| 524 | mov di,offset LAST:ExtSizeMess ; store decimal size of ext/hi alloc | ||
| 525 | ; here | ||
| 526 | call b2asc10 | ||
| 527 | |||
| 528 | mov ax,[sys_size] | ||
| 529 | mov di,offset LAST:SysSizeMess ; system memory allocated | ||
| 530 | call b2asc10 | ||
| 531 | ; | ||
| 532 | mov ax,[PF_Base] ; page frame base addr | ||
| 533 | shr ax,8 ; shift right to get significant digits | ||
| 534 | mov di,offset LAST:PFBAMess+1; where to put ascii base address | ||
| 535 | base_loop: | ||
| 536 | push ax ; save all digits | ||
| 537 | and ax,0fh ; get one digit | ||
| 538 | cmp ax,9 ; q: digit <=9 | ||
| 539 | jbe skip_dig_adj ; y: don't adjust | ||
| 540 | add ax,'A'-':' | ||
| 541 | skip_dig_adj: | ||
| 542 | add ax,'0' ; make it ascii | ||
| 543 | mov CS:[di],al ; store in message | ||
| 544 | dec di ; update pointer | ||
| 545 | pop ax ; get all digits back | ||
| 546 | ; shift right for next digit | ||
| 547 | shr ax,4 ; q: done? | ||
| 548 | jnz base_loop ; n: do another | ||
| 549 | ; y: print it | ||
| 550 | mov dx,offset LAST:InstallMess | ||
| 551 | PRINT_MSG | ||
| 552 | ; | ||
| 553 | ; mov dx,offset LAST:AutoMess ; assume AUTO | ||
| 554 | ; cmp [Auto_Mode],0 ;Q: auto mode ? | ||
| 555 | ; jne print_mode ; Y: display message | ||
| 556 | ; mov dx,offset LAST:InactiveMess ; N: assume OFF | ||
| 557 | ; cmp [Active_Status],0 ; q: OFF specified? | ||
| 558 | ; jz print_mode ; y | ||
| 559 | ; mov dx,offset LAST:ActiveMess ; n | ||
| 560 | ;print_mode: | ||
| 561 | ; PRINT_MSG | ||
| 562 | ; | ||
| 563 | ; Ok, now we can patch int15h - must be careful not to install | ||
| 564 | ; patch when Active_Status set, but not in virtual mode | ||
| 565 | ; | ||
| 566 | pushf | ||
| 567 | cli ; clear ints | ||
| 568 | xor ax,ax | ||
| 569 | mov ds,ax ; DS -> 0:0 | ||
| 570 | ASSUME DS:ABS0 | ||
| 571 | les bx,dword ptr [i15_vector] ; DS:BX -> pts to old one | ||
| 572 | mov ax,offset R_CODE:i15_Entry | ||
| 573 | mov [i15_vector],ax ; set new ip | ||
| 574 | mov ax,seg R_CODE ; | ||
| 575 | mov [i15_vector+2],ax ; set new cs | ||
| 576 | mov ds,ax ; DS -> R_CODE | ||
| 577 | ASSUME DS:R_CODE | ||
| 578 | mov [i15_Old],bx ; save old IP | ||
| 579 | mov [i15_Old+2],es ; save old CS | ||
| 580 | popf ; restore IF | ||
| 581 | mov ax,seg DGROUP | ||
| 582 | mov ds,ax ; DS -> dgroup | ||
| 583 | ASSUME DS:DGROUP | ||
| 584 | ; | ||
| 585 | ; now patch int67 for EMM functions | ||
| 586 | ; | ||
| 587 | pushf | ||
| 588 | cli ; clear ints | ||
| 589 | xor ax,ax | ||
| 590 | mov ds,ax ; DS -> 0:0 | ||
| 591 | ASSUME DS:ABS0 | ||
| 592 | mov ax,offset R_CODE:EMM_rEntry | ||
| 593 | mov [i67_vector],ax ; set new ip | ||
| 594 | mov ax,seg R_CODE ; | ||
| 595 | mov [i67_vector+2],ax ; set new cs | ||
| 596 | popf ; restore IF | ||
| 597 | mov ax,seg DGROUP | ||
| 598 | mov ds,ax ; DS -> dgroup | ||
| 599 | ASSUME DS:DGROUP | ||
| 600 | ; | ||
| 601 | ; all done with no errors | ||
| 602 | ; | ||
| 603 | xor ax,ax ; NO errors | ||
| 604 | ; | ||
| 605 | IE_leave: | ||
| 606 | pop es | ||
| 607 | pop ds | ||
| 608 | pop di | ||
| 609 | pop bp | ||
| 610 | pop dx | ||
| 611 | pop bx | ||
| 612 | ret | ||
| 613 | ; | ||
| 614 | IE_not_installed: | ||
| 615 | call DeallocMem ; put back any memory we took | ||
| 616 | mov ax,ERROR ; error return | ||
| 617 | jmp IE_leave | ||
| 618 | ; | ||
| 619 | Init_MEMM386 endp | ||
| 620 | |||
| 621 | ; | ||
| 622 | page | ||
| 623 | ;****************************************************************************** | ||
| 624 | ; | ||
| 625 | ; parser - parse out MEMM parameters and set appropriate values | ||
| 626 | ; for expanded memory size ([pool_size]), page frame base | ||
| 627 | ; address ([PF_Base]) | ||
| 628 | ; | ||
| 629 | ; entry: es:di == config.sys command line parameters | ||
| 630 | ; ds = DGROUP | ||
| 631 | ; | ||
| 632 | ; exit: [pool_size] = expanded memory size | ||
| 633 | ; [PF_Base] = page frame base address | ||
| 634 | ; [Active_Status] =flag for virtual/real mode exit | ||
| 635 | ; [msg_flag] = appropriate messages to display | ||
| 636 | ; | ||
| 637 | ; used: none | ||
| 638 | ; | ||
| 639 | ;****************************************************************************** | ||
| 640 | ; | ||
| 641 | parser proc near | ||
| 642 | push ax ; BP+16 | ||
| 643 | push bx ; BP+14 | ||
| 644 | push cx ; BP+12 | ||
| 645 | push dx ; BP+10 | ||
| 646 | push si ; BP+8 | ||
| 647 | push di ; BP+6 | ||
| 648 | push bp ; BP+4 | ||
| 649 | push ds ; BP+2 | ||
| 650 | push es ; BP+0 | ||
| 651 | mov bp,sp ; | ||
| 652 | cld ; make sure we go forward | ||
| 653 | xor ax,ax ; clear accumulator | ||
| 654 | ; | ||
| 655 | ; Skip past MEMM.EXE in command line | ||
| 656 | ; | ||
| 657 | parm1_loop: ; find 1st parameter | ||
| 658 | mov al,es:[di] | ||
| 659 | cmp al,' ' ; q: find end of MEMM.exe? | ||
| 660 | jbe ploop1 ; y: start parsing | ||
| 661 | inc di ; n: try next one | ||
| 662 | jmp short parm1_loop | ||
| 663 | jmp_def: | ||
| 664 | jmp set_def | ||
| 665 | ; | ||
| 666 | jmp_PF: | ||
| 667 | jmp chk_PF | ||
| 668 | ; | ||
| 669 | ;jmp_onf: | ||
| 670 | ; jmp chk_onf | ||
| 671 | ; | ||
| 672 | ;jmp_auto: | ||
| 673 | ; jmp chk_auto | ||
| 674 | ; | ||
| 675 | jmp_Hx: | ||
| 676 | jmp chk_Hx | ||
| 677 | ; | ||
| 678 | jmp_Xs: | ||
| 679 | jmp chk_Xs | ||
| 680 | |||
| 681 | ploop1: | ||
| 682 | mov si,offset DGROUP:arg_str; ds:si = storage for argument | ||
| 683 | mov cx,max_arg_len ; maximum length of argument | ||
| 684 | call get_token_far ; get next token | ||
| 685 | or cx,cx ; q: anything there? | ||
| 686 | jz jmp_def ; n: go set default values | ||
| 687 | lodsb ; y: get 1st char | ||
| 688 | cmp al,'m' ; q: PF base address? | ||
| 689 | je jmp_PF ; maybe: go validate it | ||
| 690 | cmp al,'h' ; q: Himem enable /disable? | ||
| 691 | je jmp_Hx ; maybe: go validate it | ||
| 692 | cmp al,'x' ; q: Exclude segment parameter | ||
| 693 | je jmp_Xs ; maybe: go validate it | ||
| 694 | ; cmp al,'o' ; q: ON/OFF? | ||
| 695 | ; je jmp_onf ; maybe: go validate it | ||
| 696 | ; cmp al,'a' ; q: AUTO? | ||
| 697 | ; je jmp_auto ; maybe: go validate it | ||
| 698 | |||
| 699 | cmp al,'0' ; q: is it a digit (size) | ||
| 700 | jb inv_parm ; n: invalid | ||
| 701 | cmp al,'9' ; q: is it a digit? | ||
| 702 | jbe chk_siz ; y: validate the size | ||
| 703 | inv_parm: | ||
| 704 | or [msg_flag],INV_PARM_MSG ; set invalid parameter flag | ||
| 705 | jmp short ploop1 ; continue | ||
| 706 | chk_siz: | ||
| 707 | mov bx,cx ; bx = number of digits | ||
| 708 | mov byte ptr [bx+si-1],' ' ; terminate string | ||
| 709 | mov cx,10 ; decimal multiplier | ||
| 710 | xor dx,dx ; clear upper 16 bits | ||
| 711 | xor bx,bx ; clear temporary accumulator | ||
| 712 | cmp [pool_size],0 ; q: have we already done this? | ||
| 713 | jz dig_loop ; n: continue | ||
| 714 | mov dx,1 ; y: skip all of this | ||
| 715 | dig_loop: | ||
| 716 | or dx,dx ; q: overflow? | ||
| 717 | jnz new_digit ; y: just skip rest of digits | ||
| 718 | sub al,'0' ; get ones value | ||
| 719 | xchg ax,bx ; swap accumulated value to ax | ||
| 720 | mul cx ; times 10 | ||
| 721 | add ax,bx ; add in ones value | ||
| 722 | adc dx,0 ; carry to dx | ||
| 723 | xchg ax,bx ; temporary value to bx | ||
| 724 | ; | ||
| 725 | new_digit: | ||
| 726 | lodsb ; get new char into al | ||
| 727 | cmp al,'0' ; q: between 0 & 9? | ||
| 728 | jb dig_exit ; n: done | ||
| 729 | cmp al,'9' | ||
| 730 | ja dig_exit | ||
| 731 | jmp dig_loop ; y: process it | ||
| 732 | ; | ||
| 733 | dig_exit: | ||
| 734 | cmp al,' ' ; q: any invalid digits? | ||
| 735 | jne ck_inv_parm ; y: invalid parameter | ||
| 736 | or dx,dx ; q: something wrong? | ||
| 737 | jz chk_siz1 ; n: not yet | ||
| 738 | cmp [pool_size],0 ; q: is this the second time for size? | ||
| 739 | jz siz_adj ; n: they just asked for too much | ||
| 740 | ck_inv_parm: | ||
| 741 | or [msg_flag],INV_PARM_MSG ; y: only let them do it once | ||
| 742 | jmp ploop1 ; continue | ||
| 743 | chk_siz1: | ||
| 744 | cmp bx,16 ;q: did they ask for too little? | ||
| 745 | jb siz_adj ; y: go adjust it | ||
| 746 | cmp bx,MAX_SIZE ;q: too much? | ||
| 747 | ja siz_adj ; y: adjust it | ||
| 748 | mov dx,0fh ; n: make sure it was a multiple of 16k | ||
| 749 | and dx,bx ;q: was it? | ||
| 750 | jz set_siz ; y: no problem | ||
| 751 | sub bx,dx ; n: drop it down | ||
| 752 | jmp siz_msg ; and give them the message | ||
| 753 | siz_adj: | ||
| 754 | mov bx,256 ; default value for size | ||
| 755 | siz_msg: | ||
| 756 | or [msg_flag],SIZE_ADJ_MSG ; size adjusted | ||
| 757 | set_siz: | ||
| 758 | mov [pool_size],bx ; save it | ||
| 759 | jmp ploop1 ; go check more parameters | ||
| 760 | |||
| 761 | |||
| 762 | ; | ||
| 763 | ; Check page frame base address | ||
| 764 | ; | ||
| 765 | chk_PF: | ||
| 766 | cmp cx,2 ; q: 2 and only 2 chars in argument? | ||
| 767 | jne inv_prm ; n: error | ||
| 768 | lodsb ; get Mx specifier | ||
| 769 | cmp [PF_Base],0ffffh ; q: have they already specified this? | ||
| 770 | jnz inv_prm ; y: don't let them do it again | ||
| 771 | cmp al,'0' ; q: between 1 & 8? | ||
| 772 | jb inv_prm ; n: invalid | ||
| 773 | cmp al,'8' | ||
| 774 | ja inv_prm ; n: invalid | ||
| 775 | sub al,'0' ; make zero relative | ||
| 776 | xor ah,ah ; zero out hi bits | ||
| 777 | shl ax,1 ; make word offset | ||
| 778 | mov [PF_Base],ax ; store address | ||
| 779 | jmp ploop1 ; get next parameter | ||
| 780 | |||
| 781 | ; | ||
| 782 | ; supporting use of Hi Ram. We are providing a command line option for this | ||
| 783 | ; the parameter is specified as He for himem enable or Hd for Himem disable | ||
| 784 | ; this parameter may be specified only once in a command line. Also | ||
| 785 | ; | ||
| 786 | chk_Hx: | ||
| 787 | ; cmp cx,2 ; q: 2 and only 2 chars in argument | ||
| 788 | ; jne inv_prm ; n: error | ||
| 789 | ; lodsb ; get Hx specifier | ||
| 790 | ;; | ||
| 791 | ; cmp [himem_use],0ffh ; has this already been specified | ||
| 792 | ; jnz inv_parm | ||
| 793 | ;; | ||
| 794 | ; cmp al,'e' ; is user asking us to enable | ||
| 795 | ; jne Hx$1 ; no, go to check enable | ||
| 796 | ;; | ||
| 797 | ; mov [himem_use],01h ; enable himem use | ||
| 798 | ; jmp ploop1 | ||
| 799 | ;Hx$1: | ||
| 800 | ; cmp al,'d' | ||
| 801 | ; jne inv_parm ; if neither d or e it is invalid | ||
| 802 | ;; | ||
| 803 | ; mov [himem_use],00h | ||
| 804 | jmp ploop1 | ||
| 805 | |||
| 806 | ; | ||
| 807 | inv_prm: | ||
| 808 | or [msg_flag],INV_PARM_MSG ; invalid | ||
| 809 | jmp ploop1 ; get next parameter | ||
| 810 | ; | ||
| 811 | ; | ||
| 812 | ; check for exclusion of segments. this parameter is specfied thusly: | ||
| 813 | ; | ||
| 814 | ; X:nnnn-mmmm where nnnn is lo segment and mmmm is hi segment of range to | ||
| 815 | ; be excluded from being mappable. | ||
| 816 | ; | ||
| 817 | ; more than one of these may be specified. | ||
| 818 | ; | ||
| 819 | chk_Xs: | ||
| 820 | call handle_Xswitch | ||
| 821 | jc inv_parm | ||
| 822 | jmp ploop1 | ||
| 823 | ; | ||
| 824 | ; | ||
| 825 | ; Check for ON/OFF | ||
| 826 | ; | ||
| 827 | ;chk_onf: | ||
| 828 | ; lodsb ; get next char | ||
| 829 | ; cmp [Active_Status],1 ; q: have they already specified this? | ||
| 830 | ; jbe inv_prm ; y: ignore and set error flag | ||
| 831 | ; cmp [Auto_Mode],1 ; n:q: have they specified auto_mode? | ||
| 832 | ; je inv_prm ; y: ignore and set error flag | ||
| 833 | ; cmp al,'n' ; q: on? | ||
| 834 | ; jne onf_cont ; n: continue | ||
| 835 | ; cmp cx,2 ; y: is that all there is? | ||
| 836 | ; jne inv_prm ; n: error | ||
| 837 | ; mov [Active_Status],1 ; y: set on | ||
| 838 | ; mov [Auto_Mode],0 ; clear Auto mode | ||
| 839 | ; jmp ploop1 ; get next parameter | ||
| 840 | ;onf_cont: | ||
| 841 | ; cmp al,'f' ; q: OF? | ||
| 842 | ; jne inv_prm ; n: invalid | ||
| 843 | ; lodsb ; y: get next char | ||
| 844 | ; cmp al,'f' ; q: OFF? | ||
| 845 | ; jne inv_prm ; n: invalid | ||
| 846 | ; cmp cx,3 ; q: is that all there is? | ||
| 847 | ; jne inv_prm ; n: error | ||
| 848 | ; mov [Active_Status],0 ; y: set OFF | ||
| 849 | ; mov [Auto_Mode],0 ; clear Auto mode | ||
| 850 | ; jmp ploop1 ; get next parameter | ||
| 851 | ; | ||
| 852 | ; Check for AUTO | ||
| 853 | ; | ||
| 854 | ;chk_auto: | ||
| 855 | ; cmp [Active_Status],1 ; q: have they already specified ON/OFF? | ||
| 856 | ; jbe inv_prm ; y: ignore and set error flag | ||
| 857 | ; cmp [Auto_Mode],1 ; n:q: have they specified auto_mode? | ||
| 858 | ; je inv_prm ; y: ignore and set error flag | ||
| 859 | ; cmp cx,AUTO_LEN ; n: q: parameter correct length ? | ||
| 860 | ; jne inv_prm ; n: ignore and set error flag | ||
| 861 | ; push es ; y: check for 'AUTO' | ||
| 862 | ; push di | ||
| 863 | ; dec si ; DS:SI pts to begin of arg | ||
| 864 | ; mov di,offset LAST:AUTO_parm | ||
| 865 | ; push cs | ||
| 866 | ; pop es ; ES:DI pts to 'AUTO' | ||
| 867 | ; cld | ||
| 868 | ; repe cmpsb ;Q: do CX bytes compare ? | ||
| 869 | ; pop di ; restore DI | ||
| 870 | ; pop es ; restore ES | ||
| 871 | ; jne inv_prm ; N: invalid parameter message | ||
| 872 | ; mov [Auto_Mode],1 ; Y: set AUTO mode | ||
| 873 | ; jmp ploop1 ; get next parameter | ||
| 874 | ; | ||
| 875 | ; Set default values for those items that were not specified | ||
| 876 | ; | ||
| 877 | set_def: | ||
| 878 | |||
| 879 | ; | ||
| 880 | ; default pool size if not defined is 256k | ||
| 881 | ; | ||
| 882 | set_pool_size: | ||
| 883 | cmp [pool_size],0 ; q: did they specify size? | ||
| 884 | jnz set_himem ; y: ok | ||
| 885 | mov [pool_size],256 ; n: set default | ||
| 886 | or [msg_flag],SIZE_ADJ_MSG ; display size adjusted | ||
| 887 | |||
| 888 | ; | ||
| 889 | ; default of use of hi system ram is that it should not be used | ||
| 890 | ; | ||
| 891 | set_himem: | ||
| 892 | ; cmp [himem_use],0ffh ; q:did they specify himem enb/dsb | ||
| 893 | ; jnz parse_xit ; y: ok | ||
| 894 | ; mov [himem_use],0 ; n: set default that it is not used | ||
| 895 | |||
| 896 | parse_xit: ; restore registers and exit | ||
| 897 | pop es | ||
| 898 | pop ds | ||
| 899 | pop bp | ||
| 900 | pop di | ||
| 901 | pop si | ||
| 902 | pop dx | ||
| 903 | pop cx | ||
| 904 | pop bx | ||
| 905 | pop ax | ||
| 906 | ret | ||
| 907 | parser endp | ||
| 908 | ; | ||
| 909 | ; parser local data | ||
| 910 | ; | ||
| 911 | ;AUTO_parm db "auto" | ||
| 912 | ;AUTO_LEN equ $-AUTO_parm | ||
| 913 | |||
| 914 | |||
| 915 | msg_tbl label word | ||
| 916 | dw offset LAST:Incorrect_PRT ; Incorrect Processor Type | ||
| 917 | dw offset LAST:Incorrect_DOS ; Incorrect Version of DOS | ||
| 918 | dw offset LAST:InsfMem ; Insufficient Memory | ||
| 919 | dw offset LAST:Already_Inst ; Already Installed | ||
| 920 | dw offset LAST:No_PF_Avail ; No Page Frame Space Avail | ||
| 921 | kill_end label word ; End of messages that kill driver | ||
| 922 | dw offset LAST:Adj_Size ; Pool Size Adjusted | ||
| 923 | dw offset LAST:InvPFBA ; Page Frame Base Addr Adjusted | ||
| 924 | dw offset LAST:InvMRA ; Map Register Adjusted | ||
| 925 | dw offset LAST:InvParm ; Invalid Parameter msg | ||
| 926 | dw offset LAST:PFWarning ; Page Frame warning message | ||
| 927 | MAX_MSG equ (this byte - msg_tbl)/2 ; # of messages to display | ||
| 928 | KILL_MSG equ (this byte - kill_end)/2; 1st four will abort driver | ||
| 929 | ; | ||
| 930 | |||
| 931 | page | ||
| 932 | ;****************************************************************************** | ||
| 933 | ; handle_Xswitch - processes the X switch to make some segments non-mappable ; | ||
| 934 | ; ; | ||
| 935 | ; entry: ds:di string with X switch parameters in form "X:nnnn-mmmm" ; | ||
| 936 | ; cx is length of string | ||
| 937 | ; ; | ||
| 938 | ; exit: CY set if invalid parameter ; | ||
| 939 | ; CY clear if parameter processed ; | ||
| 940 | ; and non-mappable segments excluded ; | ||
| 941 | ; ; | ||
| 942 | ; uses: flags,ax,cx,si ; | ||
| 943 | ; ; | ||
| 944 | ; author: ISP 8/24/88 ; | ||
| 945 | ; ; | ||
| 946 | ;*****************************************************************************; | ||
| 947 | handle_XSwitch proc near | ||
| 948 | ; | ||
| 949 | cmp cx,5 ; must have atleast 5 symbols | ||
| 950 | jb error_Xs ; | ||
| 951 | ; | ||
| 952 | lodsb ; get the next letter ":" | ||
| 953 | sub cx,2 ; | ||
| 954 | ; | ||
| 955 | cmp al,":" ; is it ":" | ||
| 956 | jne error_Xs ; if not it is a bad parameter | ||
| 957 | ; | ||
| 958 | call htoi ; convert hex to integer | ||
| 959 | jcxz error_Xs ; if we have run out we have a bad parameter | ||
| 960 | ; | ||
| 961 | mov bx,ax ; save in bx the start segment to be excluded | ||
| 962 | ; | ||
| 963 | lodsb ; get the next letter | ||
| 964 | dec cx ; | ||
| 965 | jcxz error_Xs | ||
| 966 | cmp al,"-" ; is it the letter "-" | ||
| 967 | jnz error_Xs ; | ||
| 968 | ; | ||
| 969 | call htoi ; convert hex to mappable | ||
| 970 | call exclude_segments | ||
| 971 | |||
| 972 | clc ; set success and | ||
| 973 | ret ; return | ||
| 974 | error_Xs: | ||
| 975 | stc ; set error and | ||
| 976 | ret ; return | ||
| 977 | ; | ||
| 978 | handle_XSwitch endp | ||
| 979 | |||
| 980 | ;-----------------------------------------------------------------------; | ||
| 981 | ; htoi ; | ||
| 982 | ; ; | ||
| 983 | ; Converts a string to an integer. ; | ||
| 984 | ; ; | ||
| 985 | ; Arguments: ; | ||
| 986 | ; DS:SI = string ; | ||
| 987 | ; CX = length ; | ||
| 988 | ; Returns: ; | ||
| 989 | ; AX = integer ; | ||
| 990 | ; DS:SI = remaining string ; | ||
| 991 | ; CX = remaining length ; | ||
| 992 | ; Alters: ; | ||
| 993 | ; nothing ; | ||
| 994 | ; Calls: ; | ||
| 995 | ; nothing ; | ||
| 996 | ; History: ; | ||
| 997 | ; ; | ||
| 998 | ; ISP (isp) 8/24/88 shifted from ps2emm srces ; | ||
| 999 | ;-----------------------------------------------------------------------; | ||
| 1000 | |||
| 1001 | |||
| 1002 | htoi proc near | ||
| 1003 | push bx | ||
| 1004 | xor ax,ax | ||
| 1005 | mov bx,ax | ||
| 1006 | htoi_loop: | ||
| 1007 | jcxz htoi_done | ||
| 1008 | |||
| 1009 | ; get the next character | ||
| 1010 | |||
| 1011 | mov bl,[si] | ||
| 1012 | inc si | ||
| 1013 | dec cx | ||
| 1014 | |||
| 1015 | ; see if it's a digit | ||
| 1016 | |||
| 1017 | sub bl,'0' | ||
| 1018 | cmp bl,9 | ||
| 1019 | jbe have_hvalue | ||
| 1020 | sub bl,'A'-'0' | ||
| 1021 | cmp bl,'F'-'A' | ||
| 1022 | jbe have_hvalue_but_10 | ||
| 1023 | sub bl,'a'-'A' | ||
| 1024 | cmp bl,'F'-'A' | ||
| 1025 | ja htoi_not_digit | ||
| 1026 | have_hvalue_but_10: | ||
| 1027 | add bl,10 | ||
| 1028 | have_hvalue: | ||
| 1029 | |||
| 1030 | ; shift and add | ||
| 1031 | |||
| 1032 | shl ax,1 | ||
| 1033 | shl ax,1 | ||
| 1034 | shl ax,1 | ||
| 1035 | shl ax,1 | ||
| 1036 | add ax,bx | ||
| 1037 | jmp htoi_loop | ||
| 1038 | htoi_not_digit: | ||
| 1039 | inc cx ; give back the character | ||
| 1040 | dec si | ||
| 1041 | htoi_done: | ||
| 1042 | pop bx | ||
| 1043 | ret | ||
| 1044 | htoi endp | ||
| 1045 | |||
| 1046 | |||
| 1047 | |||
| 1048 | page | ||
| 1049 | ;****************************************************************************** | ||
| 1050 | ; | ||
| 1051 | ; b2asc10 - converts binary to ascii decimal and store at CS:DI | ||
| 1052 | ; stores 5 ascii chars (decimal # is right justified and | ||
| 1053 | ; filled on left with blanks) | ||
| 1054 | ; | ||
| 1055 | ; entry: ax = binary number | ||
| 1056 | ; DS = DGROUP | ||
| 1057 | ; CS:di = place to store ascii chars. | ||
| 1058 | ; | ||
| 1059 | ; exit: ASCII decimal representation of number stored at DS:DI | ||
| 1060 | ; | ||
| 1061 | ; used: none | ||
| 1062 | ; | ||
| 1063 | ; stack: | ||
| 1064 | ; | ||
| 1065 | ;****************************************************************************** | ||
| 1066 | ; | ||
| 1067 | b2asc10 proc near | ||
| 1068 | ; | ||
| 1069 | push ax | ||
| 1070 | push bx | ||
| 1071 | push cx | ||
| 1072 | push dx | ||
| 1073 | push si | ||
| 1074 | push di | ||
| 1075 | ; | ||
| 1076 | mov si,8 ; pointer to base 10 table | ||
| 1077 | xor bl,bl ; leading zeroes flag | ||
| 1078 | ; | ||
| 1079 | ; convert binary number to decimal ascii | ||
| 1080 | ; | ||
| 1081 | b2_loop: | ||
| 1082 | xor dx,dx ; clear word extension | ||
| 1083 | mov cx,powr10[si] | ||
| 1084 | div cx ; divide by power of 10 | ||
| 1085 | or bl,bl | ||
| 1086 | jnz b2_ascii | ||
| 1087 | ; | ||
| 1088 | or ax,ax ; q: zero result? | ||
| 1089 | jnz b2_ascii ; n: go convert to ascii | ||
| 1090 | ; | ||
| 1091 | mov al,' ' ; y: go blank fill | ||
| 1092 | jmp b2_make_strg ; | ||
| 1093 | ; | ||
| 1094 | b2_ascii: | ||
| 1095 | add al,'0' ; put into ascii format | ||
| 1096 | mov bl,1 ; leading zeroes on | ||
| 1097 | ; | ||
| 1098 | b2_make_strg: | ||
| 1099 | mov CS:[di],al ; put ascii number into string | ||
| 1100 | xchg ax,dx | ||
| 1101 | inc di ; increment buffer string pointer | ||
| 1102 | dec si ; decrement power of 10 pointer | ||
| 1103 | dec si ; | ||
| 1104 | jge b2_loop ; Q: Last digit? N: Jump if not | ||
| 1105 | ; | ||
| 1106 | pop di | ||
| 1107 | pop si | ||
| 1108 | pop dx | ||
| 1109 | pop cx | ||
| 1110 | pop bx | ||
| 1111 | pop ax | ||
| 1112 | ret ; *** return *** | ||
| 1113 | ; | ||
| 1114 | b2asc10 endp | ||
| 1115 | ; | ||
| 1116 | |||
| 1117 | LAST ends ; End of segment | ||
| 1118 | ; | ||
| 1119 | |||
| 1120 | end ; End of module | ||
| 1121 | |||
| 1122 | |||
| 1123 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/INITDEB.ASM b/v4.0/src/MEMM/MEMM/INITDEB.ASM new file mode 100644 index 0000000..76db0dc --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INITDEB.ASM | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title InitDeb - initialize debugger | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: InitDeb - initialize debugger | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 16,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/16/86 Original from VDM MAIN.ASM module | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ; | ||
| 32 | ; Functional Description: | ||
| 33 | ; | ||
| 34 | ; This routine is linked in when linking with the kernel debugger. | ||
| 35 | ; InitDeb calls the debugger initialization routine. | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; P U B L I C S | ||
| 42 | ;****************************************************************************** | ||
| 43 | |||
| 44 | public InitDeb | ||
| 45 | |||
| 46 | ;****************************************************************************** | ||
| 47 | ; D E F I N E S | ||
| 48 | ;****************************************************************************** | ||
| 49 | include VDMseg.inc | ||
| 50 | include VDMsel.inc | ||
| 51 | |||
| 52 | FALSE equ 0 | ||
| 53 | TRUE equ not FALSE | ||
| 54 | CR equ 0dh | ||
| 55 | LF equ 0ah | ||
| 56 | |||
| 57 | MASTER_IMR equ 21h ; mask port for master 8259 | ||
| 58 | |||
| 59 | ; | ||
| 60 | ; Definition of the packet used in debug initialization. A pointer to | ||
| 61 | ; this structure is passed to Debug_Entry. | ||
| 62 | ; | ||
| 63 | DebugInit struc | ||
| 64 | CSseg dw ? ;Real mode code segment | ||
| 65 | DSseg dw ? ;Real mode data segment | ||
| 66 | CSsel dw ? ;Prot mode code selector | ||
| 67 | DSsel dw ? ;Prot mode data selector | ||
| 68 | SpareSel1 dw ? ;Prot mode alias selector 1 | ||
| 69 | SpareSel2 dw ? ;Prot mode alias selector 2 | ||
| 70 | GDTalias dw ? ;Prot mode GDT r/w alias | ||
| 71 | ProtIDTaddr dq ? ;Prot mode IDT base & limit | ||
| 72 | RealIDTaddr dq ? ;Real mode IDT base & limit | ||
| 73 | BrkFlag db ? ;TRUE if break to debugger | ||
| 74 | ComFlag db ? ;TRUE if com1, FALSE if com2 | ||
| 75 | DebugInit ends | ||
| 76 | |||
| 77 | |||
| 78 | ;****************************************************************************** | ||
| 79 | ; E X T E R N A L R E F E R E N C E S | ||
| 80 | ;****************************************************************************** | ||
| 81 | ifndef NoBugMode | ||
| 82 | dcode segment | ||
| 83 | extrn _Debug_Entry:far ; (debinit.asm) | ||
| 84 | dcode ends | ||
| 85 | endif | ||
| 86 | |||
| 87 | _DATA SEGMENT | ||
| 88 | |||
| 89 | extrn GDT_Seg:word | ||
| 90 | |||
| 91 | _DATA ENDS | ||
| 92 | |||
| 93 | ;****************************************************************************** | ||
| 94 | ; S E G M E N T D E F I N I T I O N S | ||
| 95 | ;****************************************************************************** | ||
| 96 | |||
| 97 | _DATA SEGMENT | ||
| 98 | |||
| 99 | InitData DebugInit <> | ||
| 100 | |||
| 101 | _DATA ENDS | ||
| 102 | |||
| 103 | ; | ||
| 104 | ; code | ||
| 105 | ; | ||
| 106 | LAST SEGMENT | ||
| 107 | |||
| 108 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 109 | |||
| 110 | ;****************************************************************************** | ||
| 111 | ; InitDeb - initialize kernel debugger | ||
| 112 | ; | ||
| 113 | ; | ||
| 114 | ; ENTRY: Real Mode | ||
| 115 | ; DS = DGROUP | ||
| 116 | ; AL = 00h => dont't break on debug init | ||
| 117 | ; AL = FFh => break on debug init | ||
| 118 | ; | ||
| 119 | ; EXIT: Real Mode | ||
| 120 | ; Kernel debugger initialized | ||
| 121 | ; | ||
| 122 | ; USED: none | ||
| 123 | ; | ||
| 124 | ;****************************************************************************** | ||
| 125 | InitDeb proc near | ||
| 126 | ; | ||
| 127 | ifndef NoBugMode | ||
| 128 | pusha | ||
| 129 | push ds | ||
| 130 | push es | ||
| 131 | ; | ||
| 132 | push ds | ||
| 133 | pop es ; ES = data | ||
| 134 | ; | ||
| 135 | mov di, offset DGROUP:InitData | ||
| 136 | |||
| 137 | mov bx, dcode | ||
| 138 | mov [di].CSseg, bx | ||
| 139 | mov bx, ddata | ||
| 140 | mov [di].DSseg, bx | ||
| 141 | mov [di].CSsel, DEBC_GSEL | ||
| 142 | mov [di].DSsel, DEBD_GSEL | ||
| 143 | mov [di].SpareSel1, DEBW1_GSEL | ||
| 144 | mov [di].SpareSel2, DEBW2_GSEL | ||
| 145 | mov [di].GDTalias, GDTD_GSEL | ||
| 146 | mov [di].BrkFlag, al ; ? break on entry ? | ||
| 147 | mov [di].ComFlag, FALSE ; com2 | ||
| 148 | |||
| 149 | sidt [di].RealIDTaddr | ||
| 150 | |||
| 151 | push ds | ||
| 152 | push di | ||
| 153 | mov ax, [GDT_Seg] | ||
| 154 | mov ds, ax | ||
| 155 | |||
| 156 | lgdt qword ptr ds:[GDTD_GSEL] | ||
| 157 | |||
| 158 | mov si, IDTD_GSEL | ||
| 159 | mov cx, 6 | ||
| 160 | lea di, [di].ProtIDTaddr | ||
| 161 | cld | ||
| 162 | rep movsb | ||
| 163 | pop di | ||
| 164 | pop ds | ||
| 165 | |||
| 166 | call _Debug_Entry | ||
| 167 | ; | ||
| 168 | ; and return | ||
| 169 | ; | ||
| 170 | pop es | ||
| 171 | pop ds | ||
| 172 | popa | ||
| 173 | endif | ||
| 174 | ret | ||
| 175 | InitDeb endp | ||
| 176 | |||
| 177 | |||
| 178 | LAST ends | ||
| 179 | |||
| 180 | END | ||
diff --git a/v4.0/src/MEMM/MEMM/INITEPG.ASM b/v4.0/src/MEMM/MEMM/INITEPG.ASM new file mode 100644 index 0000000..7129b17 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INITEPG.ASM | |||
| @@ -0,0 +1,377 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title InitEPage - initialize EMM Page pointers | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: InitEPage - initialize EMM Page pointers | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 4,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/06/86 0.04 _pft386 changed to a ptr | ||
| 29 | ; 07/06/86 0.04 fixed hdma_exit label to edma_exit | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 31 | ; 07/09/86 0.05 added to FindDMA routine | ||
| 32 | ; | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional Description: | ||
| 36 | ; | ||
| 37 | ; This module initializes the array of pointers to the EMM Pages used | ||
| 38 | ; by the expanded memory manager code. Specifically, this module initializes | ||
| 39 | ; the array EMM_PTE. | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .lfcond ; list false conditionals | ||
| 43 | .386p | ||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; P U B L I C D E C L A R A T I O N S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | public InitEPage | ||
| 50 | |||
| 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 VDMsel.inc | ||
| 58 | include desc.inc | ||
| 59 | include page.inc | ||
| 60 | include instr386.inc | ||
| 61 | include emmdef.inc | ||
| 62 | ; | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; E X T E R N A L R E F E R E N C E S | ||
| 65 | ;****************************************************************************** | ||
| 66 | ; | ||
| 67 | |||
| 68 | LAST segment | ||
| 69 | |||
| 70 | ifndef NOHIMEM | ||
| 71 | extrn Hi_Mem_Size:near | ||
| 72 | endif | ||
| 73 | |||
| 74 | extrn mappable_segs:byte | ||
| 75 | |||
| 76 | LAST ends | ||
| 77 | |||
| 78 | |||
| 79 | ABS0 segment at 0000h | ||
| 80 | ABS0 ends | ||
| 81 | |||
| 82 | |||
| 83 | _DATA segment | ||
| 84 | |||
| 85 | extrn DMA_Pages:word ; DMA EMM pages buffer | ||
| 86 | extrn DMA_PAGE_COUNT:word ; number of DMA pages | ||
| 87 | |||
| 88 | extrn xbase_addr_l:word ; 24 bit address of beginning of extended mem | ||
| 89 | extrn xbase_addr_h:byte ; pool of EMM pages. | ||
| 90 | extrn ext_size:word ; size of extended memory in kbytes | ||
| 91 | extrn sys_size:word ; size of system memory in kbytes | ||
| 92 | |||
| 93 | extrn _pft386:word ; ptr to dword array of Page Table entries | ||
| 94 | |||
| 95 | _DATA ends | ||
| 96 | |||
| 97 | ;****************************************************************************** | ||
| 98 | ; S E G M E N T D E F I N I T I O N | ||
| 99 | ;****************************************************************************** | ||
| 100 | _DATA segment | ||
| 101 | |||
| 102 | ifndef NOHIMEM | ||
| 103 | DMA_hi_begin dw 0 ; EMM page # for begin of DMA area in hi mem | ||
| 104 | DMA_hi_cnt dw 0 ; # of contiguous EMM pages in hi mem DMA area | ||
| 105 | endif | ||
| 106 | |||
| 107 | DMA_ext_begin dw 0 ; EMM page # for begin of DMA area in ext mem | ||
| 108 | DMA_ext_cnt dw 0 ; # of contiguous EMM pages in ext mem DMA area | ||
| 109 | |||
| 110 | ; | ||
| 111 | ; FindDMA variables | ||
| 112 | ; | ||
| 113 | crossed db 0 ; flag => crossed 1st 64k bndry | ||
| 114 | b_start dw 0 ; 1st EMM page before 1st 64k bndry | ||
| 115 | b_cnt dw 0 ; # of EMM pages before 1st 64k bndry | ||
| 116 | a_start dw 0 ; 1st EMM page after 1st 64k bndry | ||
| 117 | a_cnt dw 0 ; # of EMM pages after 1st 64k bndry | ||
| 118 | |||
| 119 | |||
| 120 | _DATA ends | ||
| 121 | ; | ||
| 122 | ;------------------------------------------------------------------------------ | ||
| 123 | LAST segment | ||
| 124 | assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 125 | page | ||
| 126 | ;****************************************************************************** | ||
| 127 | ; InitEPage - init EMM_PTE - array of pointers for EMM pages. | ||
| 128 | ; | ||
| 129 | ; ENTRY: Real Mode | ||
| 130 | ; DGROUP:[xbase_addr_l] = 24 bit address of beginning of extended mem | ||
| 131 | ; DGROUP:[xbase_addr_h] pool of EMM pages. | ||
| 132 | ; DGROUP:[ext_size] = size of extended memory buffer in kbytes | ||
| 133 | ; | ||
| 134 | ; EXIT: Real Mode | ||
| 135 | ; DGROUP:[DMA_Pages] = initialized to point to up to 8 physically | ||
| 136 | ; contiguous EMM pages in high memory. | ||
| 137 | ; DGROUP:[_pft386] = pts to array of ptrs for EMM Pages | ||
| 138 | ; | ||
| 139 | ; USED: Flags | ||
| 140 | ; STACK: | ||
| 141 | ;------------------------------------------------------------------------------ | ||
| 142 | InitEPage proc near | ||
| 143 | ; | ||
| 144 | PUSH_EAX | ||
| 145 | push bx | ||
| 146 | push cx | ||
| 147 | push dx | ||
| 148 | push si | ||
| 149 | push di | ||
| 150 | push ds | ||
| 151 | push es | ||
| 152 | ; | ||
| 153 | cld | ||
| 154 | ; | ||
| 155 | mov ax,seg DGROUP | ||
| 156 | mov ds,ax | ||
| 157 | mov es,ax | ||
| 158 | mov di,[_pft386] ; ES:DI points to begin of table | ||
| 159 | ; | ||
| 160 | mov bx,0 ; BX = current EMM page # | ||
| 161 | ; | ||
| 162 | ; set system memory pointers first | ||
| 163 | ; | ||
| 164 | mov cx,[sys_size] ; get size of system memory in kb | ||
| 165 | shr cx,4 ; convert to number of pages | ||
| 166 | jcxz fin_sys | ||
| 167 | mov eax,0000h*16 ; address of first system page | ||
| 168 | xor si,si ; index into mappable page array | ||
| 169 | ; | ||
| 170 | ; store in pft386 array | ||
| 171 | ; | ||
| 172 | SEP_hloop: | ||
| 173 | cmp cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 174 | jne not_this_page | ||
| 175 | ; | ||
| 176 | stosd | ||
| 177 | inc bx ; next emm page | ||
| 178 | dec cx | ||
| 179 | jcxz fin_sys ; found all pages | ||
| 180 | not_this_page: | ||
| 181 | inc si | ||
| 182 | add eax,4000h ; point to next 16k page | ||
| 183 | jmp SEP_hloop ; | ||
| 184 | fin_sys: | ||
| 185 | ; | ||
| 186 | ifndef NOHIMEM | ||
| 187 | ; | ||
| 188 | ; set high memory pointers next | ||
| 189 | ; | ||
| 190 | call Hi_Mem_Size ; CX = kbytes of high mem, | ||
| 191 | ; EAX = pointer to high mem | ||
| 192 | ;Q: any hi memory pages ? CX = pg cnt | ||
| 193 | jz IEP_ext ; N: set up ext mem pointers | ||
| 194 | ; Y: set high memory pointers | ||
| 195 | ; | ||
| 196 | ; check for contiguous EMM pages | ||
| 197 | ; | ||
| 198 | push bx ; first hi mem EMM page # | ||
| 199 | push cx ; save # of hi mem EMM pages | ||
| 200 | call FindDMA ; find the DMA pages for hi mem | ||
| 201 | mov [DMA_hi_begin],bx ; save begin EMM page # | ||
| 202 | mov [DMA_hi_cnt],cx ; save cnt | ||
| 203 | pop cx ; restore # of hi mem EMM pages | ||
| 204 | pop bx ; restore EMM page# for 1st of hi mem | ||
| 205 | ; | ||
| 206 | ; set entries in _pft386 | ||
| 207 | ; | ||
| 208 | IEP_hloop: | ||
| 209 | db 66h | ||
| 210 | stosw ; set this table entry | ||
| 211 | db 66h | ||
| 212 | add ax,4000h ; ADD EAX,4000h | ||
| 213 | dw 0000h ; EAX = addr of next EMM page | ||
| 214 | inc bx ; increment EMM page # | ||
| 215 | loop IEP_hloop ; set all high memory entries | ||
| 216 | |||
| 217 | endif ; NOHIMEM | ||
| 218 | |||
| 219 | ; | ||
| 220 | ; set extended memory entries | ||
| 221 | ; | ||
| 222 | IEP_ext: | ||
| 223 | mov cx,[ext_size] ; CX = kbytes of ext memory | ||
| 224 | shr cx,4 ;Q: any ext memory pages ? CX = pg cnt | ||
| 225 | jz IEP_Dpages ; N: all done - leave | ||
| 226 | db 66h ; Y: set ext memory pointers | ||
| 227 | mov ax,[xbase_addr_l] ; get pointer to ext memory pool | ||
| 228 | db 66h | ||
| 229 | and ax,0FFFFh ; AND EAX,00FFFFFFh | ||
| 230 | dw 00FFh ; clear highest nibble | ||
| 231 | ; | ||
| 232 | ; check for contiguous EMM pages | ||
| 233 | ; | ||
| 234 | push bx ; first ext mem EMM page # | ||
| 235 | push cx ; save # of ext mem EMM pages | ||
| 236 | call FindDMA ; find the DMA pages for ext mem | ||
| 237 | mov [DMA_ext_begin],bx ; save begin EMM page # | ||
| 238 | mov [DMA_ext_cnt],cx ; save cnt | ||
| 239 | pop cx ; restore # of ext mem EMM pages | ||
| 240 | pop bx ; restore EMM page# for 1st of ext mem | ||
| 241 | ; | ||
| 242 | ; set entries in _pft386 | ||
| 243 | ; | ||
| 244 | IEP_xloop: | ||
| 245 | db 66h | ||
| 246 | stosw ; set this table entry | ||
| 247 | db 66h | ||
| 248 | add ax,4000h ; ADD EAX,4000h | ||
| 249 | dw 0000h ; EAX = addr of next EMM page | ||
| 250 | inc bx ; increment EMM page # | ||
| 251 | loop IEP_xloop ; set all ext memory entries | ||
| 252 | ; | ||
| 253 | ; | ||
| 254 | ; set up DMA Pages | ||
| 255 | ; | ||
| 256 | IEP_Dpages: | ||
| 257 | ifndef NOHIMEM | ||
| 258 | mov ax,[DMA_hi_begin] ; SI = beginning hi mem DMA page | ||
| 259 | mov cx,[DMA_hi_cnt] ; CX = # of hi mem DMA pages | ||
| 260 | cmp cx,[DMA_ext_cnt] ;Q: more hi DMA pages ? | ||
| 261 | jae IEP_Dset ; Y: use hi mem DMA pages | ||
| 262 | endif | ||
| 263 | mov cx,[DMA_ext_cnt] ; N: use ext mem pages | ||
| 264 | mov ax,[DMA_ext_begin] | ||
| 265 | IEP_Dset: | ||
| 266 | |||
| 267 | mov DMA_Page_Count,cx | ||
| 268 | mov di,offset DGROUP:DMA_Pages ; ES:DI ->dest array | ||
| 269 | cld | ||
| 270 | DMA_Pg_St: | ||
| 271 | stosw ; store index for dma page | ||
| 272 | inc ax ; | ||
| 273 | loop DMA_Pg_St ; | ||
| 274 | ; | ||
| 275 | ; all done | ||
| 276 | ; | ||
| 277 | pop es | ||
| 278 | pop ds | ||
| 279 | pop di | ||
| 280 | pop si | ||
| 281 | pop dx | ||
| 282 | pop cx | ||
| 283 | pop bx | ||
| 284 | POP_EAX | ||
| 285 | ret | ||
| 286 | ; | ||
| 287 | InitEPage endp | ||
| 288 | ; | ||
| 289 | |||
| 290 | ;****************************************************************************** | ||
| 291 | ; FindDMA - find contiguous DMA pages | ||
| 292 | ; | ||
| 293 | ; ENTRY: Real Mode | ||
| 294 | ; EAX = 24 bits of beginning address of EMM memory pool | ||
| 295 | ; BX = first EMM page # | ||
| 296 | ; CX = # of EMM pages in this pool | ||
| 297 | ; | ||
| 298 | ; EXIT: Real Mode | ||
| 299 | ; BX = EMM page# of first DMA page | ||
| 300 | ; CX = # of DMA pages | ||
| 301 | ; | ||
| 302 | ; USED: Flags | ||
| 303 | ; STACK: | ||
| 304 | ;------------------------------------------------------------------------------ | ||
| 305 | FindDMA proc near | ||
| 306 | ; | ||
| 307 | push eax | ||
| 308 | |||
| 309 | ; | ||
| 310 | ; initialise the variables needed for this calculation | ||
| 311 | ; | ||
| 312 | mov [b_start],bx | ||
| 313 | mov [a_start],bx | ||
| 314 | mov [crossed],0 | ||
| 315 | mov [a_cnt],0 | ||
| 316 | mov [b_cnt],0 | ||
| 317 | |||
| 318 | jcxz fdp_exit ; if no pages to check exit ... | ||
| 319 | ; | ||
| 320 | ; convert physical address in eax (which is assumed to be aligned on 4k bdry) | ||
| 321 | ; to page # (in 4k physical pages) modulo 32. This is to find the page # in | ||
| 322 | ; the current 128k block | ||
| 323 | ; | ||
| 324 | shr eax,12 ; physical_address >> 4*1024 | ||
| 325 | and ax,01fh ; modulo 32, also sets Z flag if on 128k | ||
| 326 | ; bdry. So Q: On 128K bdry? | ||
| 327 | jnz fdp_loop ; N: continue as normal | ||
| 328 | mov [crossed],1 ; Y: set flag | ||
| 329 | |||
| 330 | fdp_loop: | ||
| 331 | add ax,04h ;Q: add 16k bytes, did it cross 128k ? | ||
| 332 | test ax,NOT 01fh ; if into next 128k it will go into next | ||
| 333 | ; bit | ||
| 334 | je fdp_no_cross ; N: continue | ||
| 335 | cmp [crossed],0 ; Y:Q: have we crossed it before ? | ||
| 336 | je fdp_cross1 ; N: update counts | ||
| 337 | and ax,01fh ; Y:Q: equal to 128k bndry ? | ||
| 338 | jnz fdp_exit ; N: then leave | ||
| 339 | inc [a_cnt] ; Y: update last cnt | ||
| 340 | jmp fdp_exit ; and leave | ||
| 341 | |||
| 342 | fdp_cross1: ; first crossing of 128k bndry | ||
| 343 | mov [crossed],1 ; set crossed flag. | ||
| 344 | mov [a_start],bx ; start with ... | ||
| 345 | inc [a_start] ; next page. | ||
| 346 | and ax,01fh ;Q: equal to 128k bndry ? | ||
| 347 | jnz fdp_next ; N: next page | ||
| 348 | inc [b_cnt] ; Y: include page in before pages | ||
| 349 | jmp fdp_next ; and go to next page | ||
| 350 | |||
| 351 | fdp_no_cross: | ||
| 352 | cmp [crossed],0 ;Q: have we crossed first 64k bndry ? | ||
| 353 | jne fdp_n_c ; Y: update it's count | ||
| 354 | inc [b_cnt] ; N: update before count | ||
| 355 | jmp fdp_next | ||
| 356 | fdp_n_c: | ||
| 357 | inc [a_cnt] ; update after count | ||
| 358 | fdp_next: | ||
| 359 | inc bx ; next page # | ||
| 360 | loop fdp_loop ; and continue | ||
| 361 | ; | ||
| 362 | fdp_exit: | ||
| 363 | mov bx,[b_start] ; BX = first page before | ||
| 364 | mov cx,[b_cnt] ; CX = cnt of pages before | ||
| 365 | cmp cx,[a_cnt] ;Q: more before than after ? | ||
| 366 | jae fdp_ret ; Y: return pages before | ||
| 367 | mov bx,[a_start] ; N: return pages after | ||
| 368 | mov cx,[a_cnt] ; | ||
| 369 | fdp_ret: | ||
| 370 | pop eax ; restore EAX | ||
| 371 | ret | ||
| 372 | ; | ||
| 373 | FindDMA endp | ||
| 374 | |||
| 375 | LAST ends ; end of segment | ||
| 376 | ; | ||
| 377 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/INITTAB.ASM b/v4.0/src/MEMM/MEMM/INITTAB.ASM new file mode 100644 index 0000000..c37b78e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INITTAB.ASM | |||
| @@ -0,0 +1,632 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title InitTab - OEM init routines to init tables | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: InitTab | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 4,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/21/86 0.02 Added cld | ||
| 28 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 29 | ; 07/05/86 0.04 Added NOHIMEM ifdef and added code to | ||
| 30 | ; move _TEXT segment to high mem | ||
| 31 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 32 | ; 07/06/86 0.04 added ring0 stack move | ||
| 33 | ; 07/10/86 0.05 removed CODE_GSEL reset | ||
| 34 | ; 07/10/86 0.05 PageT_Seg and PageD_Seg | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; This module is called after the system has been set up in a viable | ||
| 41 | ; state to start executing MEMM. This routine provides a "hook" where | ||
| 42 | ; the tables (GDT,IDT,TSS, & PageTables, etc) can be modified. This routine | ||
| 43 | ; must set the variables which hold the 32 bit address for each of the | ||
| 44 | ; VDM tables. This routine also sets up the EXTRA1_GSEL to point to the | ||
| 45 | ; Diagnostics byte segment. | ||
| 46 | ; | ||
| 47 | ;****************************************************************************** | ||
| 48 | .lfcond ; list false conditionals | ||
| 49 | .386p | ||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; P U B L I C D E C L A R A T I O N S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | public InitTab | ||
| 56 | |||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; L O C A L C O N S T A N T S | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; | ||
| 62 | OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr | ||
| 63 | |||
| 64 | include VDMseg.inc | ||
| 65 | include VDMsel.inc | ||
| 66 | include desc.inc | ||
| 67 | include page.inc | ||
| 68 | include instr386.inc | ||
| 69 | include oemdep.inc | ||
| 70 | ; | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; E X T E R N A L R E F E R E N C E S | ||
| 73 | ;****************************************************************************** | ||
| 74 | ; | ||
| 75 | |||
| 76 | GDT segment | ||
| 77 | extrn GDTLEN:abs | ||
| 78 | GDT ends | ||
| 79 | |||
| 80 | IDT segment | ||
| 81 | extrn IDTLEN:abs | ||
| 82 | IDT ends | ||
| 83 | |||
| 84 | TSS segment | ||
| 85 | extrn TSSLEN:abs | ||
| 86 | TSS ends | ||
| 87 | |||
| 88 | PAGESEG segment | ||
| 89 | extrn P_TABLE_CNT:abs | ||
| 90 | PAGESEG ends | ||
| 91 | |||
| 92 | |||
| 93 | _DATA segment | ||
| 94 | extrn TEXT_Seg:word ; segment for TEXT | ||
| 95 | extrn STACK_Seg:word ; segment for STACK | ||
| 96 | extrn GDT_Seg:word ; segment for GDT | ||
| 97 | extrn IDT_Seg:word ; segment for IDT | ||
| 98 | extrn TSS_Seg:word ; segment for TSS | ||
| 99 | extrn PageD_Seg:word ; segment for page dir | ||
| 100 | extrn PageT_Seg:word ; segment for page table | ||
| 101 | extrn Page_Dir:word ; 32 bit address for Page directory | ||
| 102 | extrn driver_end:dword ; ending address for MEMM.EXE | ||
| 103 | extrn _emm_brk:word ; break address for EMM data | ||
| 104 | |||
| 105 | _DATA ends | ||
| 106 | |||
| 107 | LAST segment | ||
| 108 | ifndef NOHIMEM | ||
| 109 | extrn HiSysAlloc:near ; allocate high system memory | ||
| 110 | extrn UnLockROM:near | ||
| 111 | extrn LockROM:near | ||
| 112 | endif | ||
| 113 | extrn SegTo24:near | ||
| 114 | extrn SetSegDesc:near | ||
| 115 | extrn SetPageEntry:near | ||
| 116 | extrn moveb:near | ||
| 117 | extrn get_buffer:near | ||
| 118 | |||
| 119 | LAST ends | ||
| 120 | |||
| 121 | _TEXT segment | ||
| 122 | extrn Real_Seg:word ; fixup for _TEXT in RetReal (retreal.asm) | ||
| 123 | _TEXT ends | ||
| 124 | |||
| 125 | R_CODE segment | ||
| 126 | extrn EFunTab:word ; table of ELIM functions | ||
| 127 | extrn EFUN_CNT:abs ; # of entries in table | ||
| 128 | extrn EMM_rEfix:near ; far call to EMM function dispatcher in _TEXT | ||
| 129 | R_CODE ends | ||
| 130 | |||
| 131 | |||
| 132 | ;****************************************************************************** | ||
| 133 | ; S E G M E N T D E F I N I T I O N | ||
| 134 | ;****************************************************************************** | ||
| 135 | ; | ||
| 136 | ;------------------------------------------------------------------------------ | ||
| 137 | LAST segment | ||
| 138 | assume cs:LAST, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 139 | page | ||
| 140 | ;****************************************************************************** | ||
| 141 | ; InitTab - init tables & 32 bit address | ||
| 142 | ; | ||
| 143 | ; ENTRY: Real Mode | ||
| 144 | ; GDT = current segment for GDT | ||
| 145 | ; IDT = current segment for IDT | ||
| 146 | ; TSS = current segment for TSS | ||
| 147 | ; _TEXT = current segment for _TEXT | ||
| 148 | ; STACK = current segment for STACK | ||
| 149 | ; DGROUP:[PageD_Seg] = current segment portion of page directory | ||
| 150 | ; DGROUP:[PageT_Seg] = current segment portion of page tables | ||
| 151 | ; DGROUP:[Page_Dir] = current 32 bit address for page directory | ||
| 152 | ; IDTLEN:abs = length of IDT | ||
| 153 | ; TSSLEN:abs = length of TSS | ||
| 154 | ; P_TABLE_CNT:abs = # of page TABLES | ||
| 155 | ; _TEXT:[Real_Seg] = fixup location for _TEXT in RetReal | ||
| 156 | ; R_CODE:[EFunTab] = table of ELIM functions | ||
| 157 | ; R_CODE:EFUN_CNT = # of entries in table | ||
| 158 | ; R_CODE:[EMM_rEfix] = far call to EMM function dispatcher in _TEXT | ||
| 159 | ; | ||
| 160 | ; EXIT: Real Mode | ||
| 161 | ; DGROUP:[TEXT_Seg] = current segment for TEXT | ||
| 162 | ; DGROUP:[STACK_Seg] = current segment for STACK | ||
| 163 | ; DGROUP:[GDT_Seg] = current segment for GDT | ||
| 164 | ; DGROUP:[IDT_Seg] = current segment for IDT | ||
| 165 | ; DGROUP:[TSS_Seg] = current segment for TSS | ||
| 166 | ; DGROUP:[PageD_Seg] = current segment portion of page directory | ||
| 167 | ; DGROUP:[PageT_Seg] = current segment portion of page tables | ||
| 168 | ; DGROUP:[Page_Dir] = current 32 bit address for page directory | ||
| 169 | ; DGROUP:[driver_end] = end of MEMM.EXE device driver | ||
| 170 | ; GDT:[IDTD_GSEL] = current descriptor for IDT | ||
| 171 | ; GDT:[TSS_GSEL] = current descriptor for TSS | ||
| 172 | ; GDT:[TSSD_GSEL] = current descriptor for TSS | ||
| 173 | ; GDT:[PAGET_GSEL] = current descriptor for Page TABLES | ||
| 174 | ; | ||
| 175 | ; | ||
| 176 | ; USED: Flags | ||
| 177 | ; STACK: | ||
| 178 | ;------------------------------------------------------------------------------ | ||
| 179 | InitTab proc near | ||
| 180 | ; | ||
| 181 | ifndef NOHIMEM | ||
| 182 | |||
| 183 | PUSH_EAX | ||
| 184 | push di | ||
| 185 | push ds | ||
| 186 | push es | ||
| 187 | pushf | ||
| 188 | cli ; turn off ints | ||
| 189 | cld ; strings foward | ||
| 190 | ; | ||
| 191 | mov ax,seg DGROUP | ||
| 192 | mov ds,ax | ||
| 193 | ; | ||
| 194 | ; set up GDT entry for the diagnostics segment | ||
| 195 | ; | ||
| 196 | mov ax, seg GDT ; GDT not moved yet ! | ||
| 197 | mov es,ax | ||
| 198 | |||
| 199 | xor dx,dx | ||
| 200 | mov al,00h ; only low 24 bits of address here ! | ||
| 201 | mov cx,0 ; 64k long | ||
| 202 | mov ah,D_DATA0 ; data segment | ||
| 203 | mov bx,OEM0_GSEL | ||
| 204 | call SetSegDesc ; Set up GDT alias descriptor | ||
| 205 | mov ES:[bx.BASE_XHI],01h ; set high 8 bits of address | ||
| 206 | |||
| 207 | ; | ||
| 208 | ;------------------------------------------------------------------------------ | ||
| 209 | ; Move Tables to HIGH SYSTEM memory | ||
| 210 | ; The high system memory is mapped to FE0000h - FEFFFFh | ||
| 211 | ; AND 0E0000h-0EFFFFh. The following code copies data to the E0000h | ||
| 212 | ; range | ||
| 213 | ;------------------------------------------------------------------------------ | ||
| 214 | ; | ||
| 215 | |||
| 216 | ; | ||
| 217 | ;------------------------------------------------------------------------------ | ||
| 218 | ; move PAGE DIR/TABLES up to high memory | ||
| 219 | ;------------------------------------------------------------------------------ | ||
| 220 | ; | ||
| 221 | mov ax,P_TABLE_CNT ; AX = # of page tables | ||
| 222 | inc ax ; include page directory | ||
| 223 | mov cx,ax ; CX=AX = # of pages for page table seg | ||
| 224 | call HiSysAlloc ;Q: enough room in high sys mem ? | ||
| 225 | jnc IT_move_pt ; Y: move page dir/tables to hi sys mem | ||
| 226 | inc ax ; N: Q: is error not enough room? | ||
| 227 | jnz To_IT_Exit ; Y: just go ahead and exit | ||
| 228 | popf | ||
| 229 | stc ; N: return CF = 1(mem alloc error) | ||
| 230 | jmp IT_Quit | ||
| 231 | To_IT_Exit: | ||
| 232 | jmp IT_Exit ; N: then nothing is moved up | ||
| 233 | IT_move_pt: ; | ||
| 234 | call UnLockROM ;turn off write protect | ||
| 235 | shl ax,8 ; | ||
| 236 | add ax,0E000h ; AX = segment for sys mem block | ||
| 237 | mov es,ax ; ES -> sys mem block | ||
| 238 | xor di,di ; ES:DI -> sys mem block | ||
| 239 | mov ax,[PageD_Seg] ; | ||
| 240 | mov ds,ax ; DS -> page dir/tables | ||
| 241 | xor si,si ; DS:SI -> page dir/tables | ||
| 242 | shl cx,10 ; CX = # of dwords in page tables | ||
| 243 | cld | ||
| 244 | OP32 | ||
| 245 | rep movsw ; mov cx dwords into hi sys mem | ||
| 246 | ; | ||
| 247 | mov ax,seg DGROUP | ||
| 248 | mov ds,ax ; DS = DATA | ||
| 249 | ; | ||
| 250 | ; reset break address for driver | ||
| 251 | ; | ||
| 252 | mov word ptr [driver_end],0 | ||
| 253 | mov ax,[PageD_Seg] | ||
| 254 | mov word ptr [driver_end+2],ax | ||
| 255 | |||
| 256 | ; | ||
| 257 | ; reset page dir/table pointers | ||
| 258 | XOR_EAX_EAX ; clear eax | ||
| 259 | mov ax,es ; | ||
| 260 | mov [PageD_Seg],ax ; reset segment for page dir | ||
| 261 | add ax,P_SIZE/10h ; ax = segment page table | ||
| 262 | mov [PageT_Seg],ax ; rest it | ||
| 263 | |||
| 264 | mov ax,es ; get page dir seg again | ||
| 265 | OP32 | ||
| 266 | shl ax,4 ; shl EAX,4 => EAX = 32 bit address | ||
| 267 | OP32 | ||
| 268 | mov [Page_Dir],ax ; store 32 bit addr of page dir | ||
| 269 | ; | ||
| 270 | ; reset page directory entries | ||
| 271 | ; | ||
| 272 | mov ax,word ptr [Page_Dir] ; DX,AX = 32 bit addr of Page Directory | ||
| 273 | mov dx,word ptr [Page_Dir+2] ; save it | ||
| 274 | ; | ||
| 275 | ; get addr of Page Table for Page Directory entry | ||
| 276 | ; | ||
| 277 | add ax,1000h ; add page | ||
| 278 | adc dx,0h ; carry it => DX,AX = addr of page table | ||
| 279 | ; | ||
| 280 | ; DX,AX = addr of first page table | ||
| 281 | ; | ||
| 282 | xor di,di ; ES:[DI] -> 1st entry in page dir | ||
| 283 | mov bh,0 | ||
| 284 | mov bl,P_AVAIL ; make table available to all | ||
| 285 | mov cx,P_TABLE_CNT ; set entries in page table directory | ||
| 286 | ; for existing page tables. | ||
| 287 | IT_pdir: | ||
| 288 | call SetPageEntry ; set entry for first page table | ||
| 289 | ; | ||
| 290 | ; ES:[DI] pts to next entry in page directory | ||
| 291 | add ax,1000h | ||
| 292 | adc dx,0 ; DX,AX = addr of next page table | ||
| 293 | loop IT_pdir ; set next entry in dir | ||
| 294 | ; | ||
| 295 | ; reset PAGET_GSEL descriptor | ||
| 296 | ; | ||
| 297 | mov ax,seg GDT ; GDT has not yet moved!!! | ||
| 298 | mov es,ax ; ES pts to GDT | ||
| 299 | |||
| 300 | mov ax,[PageT_Seg] ; segment for page tables | ||
| 301 | call SegTo24 | ||
| 302 | mov cx,0 ; enough room for tables | ||
| 303 | mov ah,D_DATA0 | ||
| 304 | mov bx,PAGET_GSEL | ||
| 305 | call SetSegDesc ; set up page table descriptor | ||
| 306 | ; | ||
| 307 | ; now set CR3 in the TSS - to reflect new Page DIR position | ||
| 308 | ; | ||
| 309 | mov ax,seg TSS ; TSS not moved yet !!! | ||
| 310 | mov es,ax ; ES -> TSS | ||
| 311 | xor di,di ; ES:DI -> TSS | ||
| 312 | |||
| 313 | db 66h | ||
| 314 | mov ax,[Page_Dir] ; EAX = page dir 32 bit addr | ||
| 315 | db 66h | ||
| 316 | mov word ptr ES:[di.TSS386_CR3],ax ; mov EAX into CR3 spot in TSS | ||
| 317 | ; | ||
| 318 | ;------------------------------------------------------------------------------ | ||
| 319 | ; move _TEXT, GDT,IDT, & TSS up to high system memory | ||
| 320 | ; **** this code depends on the order of the _TEXT, GDT, IDT, & TSS | ||
| 321 | ; segments when linked. They should be in the order | ||
| 322 | ; _TEXT, GDT, IDT, then TSS. | ||
| 323 | ;------------------------------------------------------------------------------ | ||
| 324 | ; | ||
| 325 | mov ax,seg TSS ; compute # of paras from begin of _TEXT | ||
| 326 | sub ax,seg _TEXT ; to begin of TSS | ||
| 327 | shl ax,4 ; convert it to bytes | ||
| 328 | add ax,TSSLEN ; and add in length of TSS | ||
| 329 | ; AX=length of _TEXT,GDT,IDT, & TSS segs | ||
| 330 | add ax,P_SIZE-1 ; round up to nearest page boundary | ||
| 331 | shr ax,12 ; AX = # of 4k pages for these tables | ||
| 332 | mov cx,ax ; CX=AX = # of pages for these tables | ||
| 333 | call HiSysAlloc ;Q: enough room in high sys mem ? | ||
| 334 | jnc IT_move_tables ; Y: move page dir/tables to hi sys mem | ||
| 335 | call LockROM ; N: move nothing. write protect ROM | ||
| 336 | jmp IT_Exit ; | ||
| 337 | IT_move_tables: | ||
| 338 | call UnLockROM ; turn off write protect | ||
| 339 | shl ax,8 ; AX = # of paras already allocated | ||
| 340 | ; in high memory | ||
| 341 | add ax,0E000h ; AX = segment for sys mem block | ||
| 342 | mov es,ax ; ES -> sys mem block | ||
| 343 | xor di,di ; ES:DI -> sys mem block | ||
| 344 | |||
| 345 | mov ax,seg _TEXT ; start with _TEXT | ||
| 346 | mov ds,ax ; DS -> _TEXT | ||
| 347 | xor si,si ; DS:SI -> _TEXT | ||
| 348 | shl cx,10 ; CX=# of dwords for _TEXT,GDT,IDT,&TSS | ||
| 349 | cld | ||
| 350 | OP32 | ||
| 351 | rep movsw ; mov _TEXT,GDT,IDT,&TSS into hi sys mem | ||
| 352 | |||
| 353 | ; | ||
| 354 | ; now reset pointers to _TEXT, GDT, IDT, & TSS | ||
| 355 | mov ax,seg DGROUP | ||
| 356 | mov ds,ax ; DS = DATA | ||
| 357 | |||
| 358 | mov ax,es ; AX = segment for new _TEXT location | ||
| 359 | mov [TEXT_Seg],ax ; set new _TEXT segment | ||
| 360 | |||
| 361 | mov bx,seg GDT | ||
| 362 | sub bx,seg _TEXT ; bx = offset from _TEXT to GDT | ||
| 363 | add ax,bx ; (don't worry, won't cross Linear 64k) | ||
| 364 | mov [GDT_Seg],ax ; set new GDT segment | ||
| 365 | |||
| 366 | mov bx,seg IDT | ||
| 367 | sub bx,seg GDT ; bx = offset from GDT to IDT | ||
| 368 | add ax,bx ; (don't worry, won't cross Linear 64k) | ||
| 369 | mov [IDT_Seg],ax ; set new IDT segment | ||
| 370 | |||
| 371 | mov bx,seg TSS | ||
| 372 | sub bx,seg IDT ; bx = offset from IDT to TSS | ||
| 373 | add ax,bx ; (don't worry, won't cross Linear 64k) | ||
| 374 | mov [TSS_Seg],ax ; set new TSS segment | ||
| 375 | ; | ||
| 376 | ; reset descriptors for _TEXT, GDT, IDT, & TSS | ||
| 377 | ; | ||
| 378 | mov ax,[GDT_Seg] ; GDT has MOVED !!! | ||
| 379 | mov es,ax ; ES pts to GDT | ||
| 380 | |||
| 381 | mov ax,[TEXT_Seg] ; _TEXT segment | ||
| 382 | call SegTo24 | ||
| 383 | mov cx,0 | ||
| 384 | mov ah,D_CODE0 | ||
| 385 | mov bx,VDMC_GSEL | ||
| 386 | call SetSegDesc ; Set up VDM code descriptor - VDMC | ||
| 387 | |||
| 388 | mov ax,[TEXT_Seg] ; _TEXT segment | ||
| 389 | call SegTo24 | ||
| 390 | mov cx,0 | ||
| 391 | mov ah,D_DATA0 | ||
| 392 | mov bx,VDMCA_GSEL | ||
| 393 | call SetSegDesc ; Set up VDM code alias descriptor | ||
| 394 | |||
| 395 | mov ax,[GDT_Seg] ; GDT segment | ||
| 396 | call SegTo24 | ||
| 397 | mov cx,GDTLEN | ||
| 398 | mov ah,D_DATA0 | ||
| 399 | mov bx,GDTD_GSEL | ||
| 400 | call SetSegDesc ; Set up GDT alias descriptor | ||
| 401 | |||
| 402 | mov ax,[IDT_Seg] ; IDT segment | ||
| 403 | call SegTo24 | ||
| 404 | mov cx,IDTLEN | ||
| 405 | mov ah,D_DATA0 | ||
| 406 | mov bx,IDTD_GSEL | ||
| 407 | call SetSegDesc ; Set up IDT alias descriptor | ||
| 408 | |||
| 409 | mov ax,[TSS_Seg] ; segment of TSS | ||
| 410 | call SegTo24 | ||
| 411 | mov cx,TSSLEN | ||
| 412 | mov ah,D_386TSS0 | ||
| 413 | mov bx,TSS_GSEL | ||
| 414 | call SetSegDesc ; Set up TSS descriptor | ||
| 415 | |||
| 416 | mov ah,D_DATA0 | ||
| 417 | mov bx,TSSD_GSEL | ||
| 418 | call SetSegDesc ; Set up TSS alias descriptor | ||
| 419 | |||
| 420 | ; | ||
| 421 | ; fixup new RING 0 stack location | ||
| 422 | ; | ||
| 423 | mov ax,[_emm_brk] ; get EMM break address | ||
| 424 | add ax,15 ; round up to next paragraph | ||
| 425 | shr ax,4 | ||
| 426 | add ax,seg _DATA ; AX = new seg address for STACK | ||
| 427 | mov [STACK_seg],ax ; save it | ||
| 428 | |||
| 429 | call SegTo24 | ||
| 430 | mov cx,offset STACK0_SIZE ; length of stack | ||
| 431 | mov ah,D_DATA0 | ||
| 432 | mov bx,VDMS_GSEL | ||
| 433 | call SetSegDesc ; Set up STACK segment GDT entry | ||
| 434 | |||
| 435 | ; | ||
| 436 | ; fixup far call / far jump references to _TEXT | ||
| 437 | ; | ||
| 438 | |||
| 439 | ; far call pointers in ELIM function table | ||
| 440 | mov ax,seg R_CODE | ||
| 441 | mov es,ax ; ES -> R_CODE | ||
| 442 | mov di,offset R_CODE:EFunTab+2 ; ES:DI -> 1st seg in func tab | ||
| 443 | mov cx,EFUN_CNT ; CX = # of dword entries | ||
| 444 | mov ax,[TEXT_Seg] | ||
| 445 | IT_Tloop: | ||
| 446 | stosw ; store new TEXT seg | ||
| 447 | inc di | ||
| 448 | inc di ; point to next seg in table | ||
| 449 | loop IT_Tloop | ||
| 450 | |||
| 451 | ; ELIM_rEntry far call | ||
| 452 | mov di,offset R_CODE:EMM_rEfix ; point to far call | ||
| 453 | mov ES:[di+3],ax ; set seg portion of call | ||
| 454 | |||
| 455 | ; Far jump in return to real code | ||
| 456 | mov es,ax ; ES -> new TEXT seg | ||
| 457 | mov di,offset _TEXT:Real_Seg ; ES:DI -> seg of far jmp | ||
| 458 | mov ES:[di],ax ; fix it | ||
| 459 | |||
| 460 | ; | ||
| 461 | ; reset break address for driver - throw away _TEXT seg and all after it | ||
| 462 | ; | ||
| 463 | mov word ptr [driver_end],10h ; just in case | ||
| 464 | mov ax,[STACK_Seg] ; begin of new stack location | ||
| 465 | add ax,STACK0_SIZE/10h ; add in size of stack | ||
| 466 | mov word ptr [driver_end+2],ax ; set break seg to end of stack | ||
| 467 | |||
| 468 | ; | ||
| 469 | ; OK, now lock high system RAM | ||
| 470 | ; | ||
| 471 | call LockROM | ||
| 472 | ; | ||
| 473 | IT_exit: | ||
| 474 | popf | ||
| 475 | clc ; No error in memory allocation attempt | ||
| 476 | IT_quit: | ||
| 477 | pop es | ||
| 478 | pop ds | ||
| 479 | pop di | ||
| 480 | POP_EAX | ||
| 481 | else | ||
| 482 | |||
| 483 | push es | ||
| 484 | push di | ||
| 485 | push eax | ||
| 486 | push dx | ||
| 487 | push cx | ||
| 488 | push bx | ||
| 489 | ; | ||
| 490 | ; try to move the pageseg up | ||
| 491 | ; | ||
| 492 | ; | ||
| 493 | ; segment to be moved up | ||
| 494 | ; | ||
| 495 | mov ax, [PageD_Seg] | ||
| 496 | mov es,ax | ||
| 497 | ; | ||
| 498 | ; its length | ||
| 499 | ; | ||
| 500 | mov ax,seg LAST | ||
| 501 | sub ax,seg PAGESEG | ||
| 502 | shl ax,4 | ||
| 503 | mov cx,ax | ||
| 504 | ; | ||
| 505 | ; we need to allocate enough to have a page aligned page directory. so | ||
| 506 | ; increase this by 4k | ||
| 507 | push cx | ||
| 508 | add cx,4*1024 | ||
| 509 | ; | ||
| 510 | ; allocate a block of memory for this | ||
| 511 | |||
| 512 | call get_buffer | ||
| 513 | pop cx | ||
| 514 | jc no_mem | ||
| 515 | ; | ||
| 516 | ; dx:ax is new address of page directory, adjust this to be page aligned | ||
| 517 | ; | ||
| 518 | add ax,4*1024 | ||
| 519 | adc dx,0 | ||
| 520 | and ax,0F000h | ||
| 521 | ; | ||
| 522 | push ax | ||
| 523 | push dx | ||
| 524 | push cx | ||
| 525 | ; | ||
| 526 | add ax,1000h | ||
| 527 | adc dx,0h | ||
| 528 | ; | ||
| 529 | ; set the entries in the page directory for these | ||
| 530 | ; | ||
| 531 | xor di,di ; es:di points to first page_dir entry | ||
| 532 | mov bh,0 | ||
| 533 | mov bl, P_AVAIL | ||
| 534 | mov cx,P_TABLE_CNT | ||
| 535 | set_entries: | ||
| 536 | call SetPageEntry | ||
| 537 | ; | ||
| 538 | ; es:di points to next entry in page directory | ||
| 539 | ; | ||
| 540 | add ax,1000h | ||
| 541 | adc dx,0 ; next page table | ||
| 542 | loop set_entries | ||
| 543 | ; | ||
| 544 | ; now we can move the page directory and tables up into extended | ||
| 545 | ; | ||
| 546 | pop cx | ||
| 547 | pop dx | ||
| 548 | pop ax | ||
| 549 | ; | ||
| 550 | xor di,di ; es:di is now the beginning, cx count of | ||
| 551 | ; number of bytes in segment and dx:ax area | ||
| 552 | ; where it is to be moved | ||
| 553 | call moveb ; move the data | ||
| 554 | jnz move_error ; there was an error in moving. the page | ||
| 555 | ; table entries need to be restored to the | ||
| 556 | ; lo memory stuff | ||
| 557 | ; | ||
| 558 | ; move succeded, fix page directory address and driver_end | ||
| 559 | ; | ||
| 560 | mov word ptr [Page_Dir],ax ; DX,AX = 32 bit addr of Page Directory | ||
| 561 | mov word ptr [Page_Dir+2],dx ; save it | ||
| 562 | ; | ||
| 563 | ; reset PAGET_GSEL descriptor | ||
| 564 | ; | ||
| 565 | mov cx,seg GDT ; GDT has not yet moved!!! | ||
| 566 | mov es,cx ; ES pts to GDT | ||
| 567 | |||
| 568 | add ax,1000h | ||
| 569 | adc dx,0 | ||
| 570 | xchg ax,dx ; for setsegdesc in opposite | ||
| 571 | ; al:dx | ||
| 572 | |||
| 573 | mov cx,0 ; enough room for tables | ||
| 574 | mov ah,D_DATA0 | ||
| 575 | mov bx,PAGET_GSEL | ||
| 576 | call SetSegDesc ; set up page table descriptor | ||
| 577 | ; | ||
| 578 | ; if we succeed in shifting the page tables up the ground is clear for us | ||
| 579 | ; to shrink the driver even more to the point where the variable emm data | ||
| 580 | ; structures end. | ||
| 581 | ; | ||
| 582 | mov ax,[_emm_brk] ; get EMM break address | ||
| 583 | add ax,15 ; round up to next paragraph | ||
| 584 | shr ax,4 | ||
| 585 | add ax,seg DGROUP ; AX = end address for driver | ||
| 586 | mov word ptr [driver_end],10h ; just in case, para offset | ||
| 587 | mov word ptr [driver_end+2],ax ; segment | ||
| 588 | |||
| 589 | |||
| 590 | no_mem: | ||
| 591 | pop bx | ||
| 592 | pop cx | ||
| 593 | pop dx | ||
| 594 | pop eax | ||
| 595 | pop di | ||
| 596 | pop es | ||
| 597 | clc | ||
| 598 | jmp end_inittab | ||
| 599 | |||
| 600 | move_error: | ||
| 601 | ; the address of page table in lo mem | ||
| 602 | ; | ||
| 603 | mov ax,[PageT_Seg] | ||
| 604 | mov cx,4 | ||
| 605 | xor dx,dx | ||
| 606 | mul cx | ||
| 607 | ; | ||
| 608 | ; set the entries in the page directory for these | ||
| 609 | ; | ||
| 610 | xor di,di ; es:di points to first page_dir entry | ||
| 611 | mov bh,0 | ||
| 612 | mov bl, P_AVAIL | ||
| 613 | mov cx,P_TABLE_CNT | ||
| 614 | restore_entries: | ||
| 615 | call SetPageEntry | ||
| 616 | ; | ||
| 617 | ; es:di points to next entry in page directory | ||
| 618 | ; | ||
| 619 | add ax,1000h | ||
| 620 | adc dx,0 ; next page table | ||
| 621 | loop restore_entries | ||
| 622 | ; | ||
| 623 | jmp no_mem | ||
| 624 | endif | ||
| 625 | end_inittab: | ||
| 626 | ret | ||
| 627 | ; | ||
| 628 | InitTab endp | ||
| 629 | ; | ||
| 630 | LAST ends ; end of segment | ||
| 631 | ; | ||
| 632 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/INSTR386.INC b/v4.0/src/MEMM/MEMM/INSTR386.INC new file mode 100644 index 0000000..490435a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/INSTR386.INC | |||
| @@ -0,0 +1,563 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: INSTR386 - 386 Instruction Macro Declaration file | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: May 11, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 05/11/86 Original | ||
| 24 | ; 06/01/86 Added operand/address size overide defines | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; 07/01/86 0.03 Added 32 arithmetic defines | ||
| 27 | ; | ||
| 28 | ;****************************************************************************** | ||
| 29 | ifndef INC_LIST | ||
| 30 | .xlist | ||
| 31 | endif | ||
| 32 | |||
| 33 | ;*** OP32_IRET - 32 bit mode iret | ||
| 34 | OP32_IRET macro | ||
| 35 | db 66h | ||
| 36 | iret | ||
| 37 | endm | ||
| 38 | |||
| 39 | ;*** OP32 - instruction prefix to invert sense of operand size attribute | ||
| 40 | |||
| 41 | OP32 macro | ||
| 42 | db 66h | ||
| 43 | endm | ||
| 44 | |||
| 45 | |||
| 46 | ;*** EA32 - instruction prefix to invert sense of effective addr attribute | ||
| 47 | |||
| 48 | EA32 macro | ||
| 49 | db 67h | ||
| 50 | endm | ||
| 51 | |||
| 52 | |||
| 53 | ;*** FS and GS overides | ||
| 54 | FSOVER macro | ||
| 55 | db 64h | ||
| 56 | endm | ||
| 57 | GSOVER macro | ||
| 58 | db 65h | ||
| 59 | endm | ||
| 60 | |||
| 61 | ; *** General Register 32 bit moves *** | ||
| 62 | |||
| 63 | MOV_EBX_EAX macro | ||
| 64 | db 66h | ||
| 65 | mov bx, ax | ||
| 66 | endm | ||
| 67 | |||
| 68 | MOV_EAX_EBX macro | ||
| 69 | db 66h | ||
| 70 | mov ax, bx | ||
| 71 | endm | ||
| 72 | |||
| 73 | MOV_ECX_EAX macro | ||
| 74 | db 66h | ||
| 75 | mov cx, ax | ||
| 76 | endm | ||
| 77 | |||
| 78 | MOV_EAX_ECX macro | ||
| 79 | db 66h | ||
| 80 | mov ax, cx | ||
| 81 | endm | ||
| 82 | |||
| 83 | MOV_EDX_EAX macro | ||
| 84 | db 66h | ||
| 85 | mov dx, ax | ||
| 86 | endm | ||
| 87 | |||
| 88 | MOV_EAX_EDX macro | ||
| 89 | db 66h | ||
| 90 | mov ax, dx | ||
| 91 | endm | ||
| 92 | |||
| 93 | MOV_EDI_EAX macro | ||
| 94 | db 66h | ||
| 95 | mov di, ax | ||
| 96 | endm | ||
| 97 | |||
| 98 | MOV_EAX_EDI macro | ||
| 99 | db 66h | ||
| 100 | mov ax, di | ||
| 101 | endm | ||
| 102 | |||
| 103 | MOV_ESI_EAX macro | ||
| 104 | db 66h | ||
| 105 | mov si, ax | ||
| 106 | endm | ||
| 107 | |||
| 108 | MOV_EAX_ESI macro | ||
| 109 | db 66h | ||
| 110 | mov ax, si | ||
| 111 | endm | ||
| 112 | |||
| 113 | MOV_EBP_EAX macro | ||
| 114 | db 66h | ||
| 115 | mov bp, ax | ||
| 116 | endm | ||
| 117 | |||
| 118 | MOV_EAX_EBP macro | ||
| 119 | db 66h | ||
| 120 | mov ax, bp | ||
| 121 | endm | ||
| 122 | |||
| 123 | MOV_ESP_EAX macro | ||
| 124 | db 66h | ||
| 125 | mov sp, ax | ||
| 126 | endm | ||
| 127 | |||
| 128 | MOV_EAX_ESP macro | ||
| 129 | db 66h | ||
| 130 | mov ax, sp | ||
| 131 | endm | ||
| 132 | |||
| 133 | ; *** Special Register/EAX 32 bit moves *** | ||
| 134 | |||
| 135 | MOV_CR0_EAX macro | ||
| 136 | db 0Fh,22h,0C0h | ||
| 137 | endm | ||
| 138 | |||
| 139 | MOV_CR0_EBX macro | ||
| 140 | db 0Fh,22h,0C3h | ||
| 141 | endm | ||
| 142 | |||
| 143 | MOV_CR0_ECX macro | ||
| 144 | db 0Fh,22h,0C1h | ||
| 145 | endm | ||
| 146 | |||
| 147 | MOV_CR0_EDX macro | ||
| 148 | db 0Fh,22h,0C2h | ||
| 149 | endm | ||
| 150 | |||
| 151 | MOV_CR0_ESP macro | ||
| 152 | db 0Fh,22h,0C4h | ||
| 153 | endm | ||
| 154 | |||
| 155 | MOV_CR0_EBP macro | ||
| 156 | db 0Fh,22h,0C5h | ||
| 157 | endm | ||
| 158 | |||
| 159 | MOV_CR0_ESI macro | ||
| 160 | db 0Fh,22h,0C6h | ||
| 161 | endm | ||
| 162 | |||
| 163 | MOV_CR0_EDI macro | ||
| 164 | db 0Fh,22h,0C7h | ||
| 165 | endm | ||
| 166 | |||
| 167 | MOV_EAX_CR0 macro | ||
| 168 | db 0Fh,20h,0C0h | ||
| 169 | endm | ||
| 170 | |||
| 171 | MOV_EBX_CR0 macro | ||
| 172 | db 0Fh,20h,0C3h | ||
| 173 | endm | ||
| 174 | |||
| 175 | MOV_ECX_CR0 macro | ||
| 176 | db 0Fh,20h,0C1h | ||
| 177 | endm | ||
| 178 | |||
| 179 | MOV_EDX_CR0 macro | ||
| 180 | db 0Fh,20h,0C2h | ||
| 181 | endm | ||
| 182 | |||
| 183 | MOV_ESP_CR0 macro | ||
| 184 | db 0Fh,20h,0C4h | ||
| 185 | endm | ||
| 186 | |||
| 187 | MOV_EBP_CR0 macro | ||
| 188 | db 0Fh,20h,0C5h | ||
| 189 | endm | ||
| 190 | |||
| 191 | MOV_ESI_CR0 macro | ||
| 192 | db 0Fh,20h,0C6h | ||
| 193 | endm | ||
| 194 | |||
| 195 | MOV_EDI_CR0 macro | ||
| 196 | db 0Fh,20h,0C7h | ||
| 197 | endm | ||
| 198 | |||
| 199 | MOV_CR2_EAX macro | ||
| 200 | db 0Fh,22h,0D0h | ||
| 201 | endm | ||
| 202 | |||
| 203 | MOV_EAX_CR2 macro | ||
| 204 | db 0Fh,20h,0D0h | ||
| 205 | endm | ||
| 206 | |||
| 207 | MOV_CR3_EAX macro | ||
| 208 | db 0Fh,22h,0D8h | ||
| 209 | endm | ||
| 210 | |||
| 211 | MOV_EAX_CR3 macro | ||
| 212 | db 0Fh,20h,0D8h | ||
| 213 | endm | ||
| 214 | |||
| 215 | MOV_DR0_EAX macro | ||
| 216 | db 0Fh,23h,0C0h | ||
| 217 | endm | ||
| 218 | |||
| 219 | MOV_DR0_EBX macro | ||
| 220 | db 0Fh,23h,0C3h | ||
| 221 | endm | ||
| 222 | |||
| 223 | MOV_DR1_EAX macro | ||
| 224 | db 0Fh,23h,0C8h | ||
| 225 | endm | ||
| 226 | |||
| 227 | MOV_DR2_EAX macro | ||
| 228 | db 0Fh,23h,0D0h | ||
| 229 | endm | ||
| 230 | |||
| 231 | MOV_DR3_EAX macro | ||
| 232 | db 0Fh,23h,0D8h | ||
| 233 | endm | ||
| 234 | |||
| 235 | MOV_DR6_EAX macro | ||
| 236 | db 0Fh,23h,0F0h | ||
| 237 | endm | ||
| 238 | |||
| 239 | MOV_DR7_EAX macro | ||
| 240 | db 0Fh,23h,0F8h | ||
| 241 | endm | ||
| 242 | |||
| 243 | MOV_EAX_DR0 macro | ||
| 244 | db 0Fh,21h,0C0h | ||
| 245 | endm | ||
| 246 | |||
| 247 | MOV_ECX_DR0 macro | ||
| 248 | db 0Fh,21h,0C1h | ||
| 249 | endm | ||
| 250 | |||
| 251 | MOV_EDX_DR0 macro | ||
| 252 | db 0Fh,21h,0C2h | ||
| 253 | endm | ||
| 254 | |||
| 255 | MOV_EAX_DR1 macro | ||
| 256 | db 0Fh,21h,0C8h | ||
| 257 | endm | ||
| 258 | |||
| 259 | MOV_EAX_DR2 macro | ||
| 260 | db 0Fh,21h,0D0h | ||
| 261 | endm | ||
| 262 | |||
| 263 | MOV_EAX_DR3 macro | ||
| 264 | db 0Fh,21h,0D8h | ||
| 265 | endm | ||
| 266 | |||
| 267 | MOV_EAX_DR6 macro | ||
| 268 | db 0Fh,21h,0F0h | ||
| 269 | endm | ||
| 270 | |||
| 271 | MOV_EAX_DR7 macro | ||
| 272 | db 0Fh,21h,0F8h | ||
| 273 | endm | ||
| 274 | |||
| 275 | MOV_TR6_EAX macro | ||
| 276 | db 0Fh,26h,0F0h | ||
| 277 | endm | ||
| 278 | |||
| 279 | MOV_EAX_TR6 macro | ||
| 280 | db 0Fh,24h,0F0h | ||
| 281 | endm | ||
| 282 | |||
| 283 | MOV_TR7_EAX macro | ||
| 284 | db 0Fh,26h,0F8h | ||
| 285 | endm | ||
| 286 | |||
| 287 | MOV_EAX_TR7 macro | ||
| 288 | db 0Fh,24h,0F8h | ||
| 289 | endm | ||
| 290 | |||
| 291 | ; *** 32 bit Register/Immediate moves *** | ||
| 292 | |||
| 293 | MOV_EAX_ macro imm | ||
| 294 | db 66h, 0B8h | ||
| 295 | dd imm | ||
| 296 | endm | ||
| 297 | |||
| 298 | MOV_EBX_ macro imm | ||
| 299 | db 66h, 0BBh | ||
| 300 | dd imm | ||
| 301 | endm | ||
| 302 | |||
| 303 | MOV_ECX_ macro imm | ||
| 304 | db 66h, 0B9h | ||
| 305 | dd imm | ||
| 306 | endm | ||
| 307 | |||
| 308 | MOV_EDX_ macro imm | ||
| 309 | db 66h, 0BAh | ||
| 310 | dd imm | ||
| 311 | endm | ||
| 312 | |||
| 313 | MOV_EDI_ macro imm | ||
| 314 | db 66h, 0BFh | ||
| 315 | dd imm | ||
| 316 | endm | ||
| 317 | |||
| 318 | MOV_ESI_ macro imm | ||
| 319 | db 66h, 0BEh | ||
| 320 | dd imm | ||
| 321 | endm | ||
| 322 | |||
| 323 | MOV_EBP_ macro imm | ||
| 324 | db 66h, 0BDh | ||
| 325 | dd imm | ||
| 326 | endm | ||
| 327 | |||
| 328 | MOV_ESP_ macro imm | ||
| 329 | db 66h, 0BCh | ||
| 330 | dd imm | ||
| 331 | endm | ||
| 332 | |||
| 333 | ; *** 32-bit immediate arithmetic instructions | ||
| 334 | |||
| 335 | ADD_EAX_ macro imm | ||
| 336 | db 66h,05h | ||
| 337 | dd imm | ||
| 338 | endm | ||
| 339 | |||
| 340 | ADD_EBX_ macro imm | ||
| 341 | db 66h,81h,0C3h | ||
| 342 | dd imm | ||
| 343 | endm | ||
| 344 | |||
| 345 | ADD_ECX_ macro imm | ||
| 346 | db 66h,81h,0C1h | ||
| 347 | dd imm | ||
| 348 | endm | ||
| 349 | |||
| 350 | ADD_EDX_ macro imm | ||
| 351 | db 66h,81h,0C2h | ||
| 352 | dd imm | ||
| 353 | endm | ||
| 354 | |||
| 355 | SUB_EAX_ macro imm | ||
| 356 | db 66h,2Dh | ||
| 357 | dd imm | ||
| 358 | endm | ||
| 359 | |||
| 360 | SUB_EBX_ macro imm | ||
| 361 | db 66h,81h,0EBh | ||
| 362 | dd imm | ||
| 363 | endm | ||
| 364 | |||
| 365 | SUB_ECX_ macro imm | ||
| 366 | db 66h,81h,0E9h | ||
| 367 | dd imm | ||
| 368 | endm | ||
| 369 | |||
| 370 | SUB_EDX_ macro imm | ||
| 371 | db 66h,81h,0EAh | ||
| 372 | dd imm | ||
| 373 | endm | ||
| 374 | |||
| 375 | CMP_EAX_ macro imm | ||
| 376 | db 66h,3Dh | ||
| 377 | dd imm | ||
| 378 | endm | ||
| 379 | |||
| 380 | CMP_EBX_ macro imm | ||
| 381 | db 66h,81h,0FBh | ||
| 382 | dd imm | ||
| 383 | endm | ||
| 384 | |||
| 385 | CMP_ECX_ macro imm | ||
| 386 | db 66h,81h,0F9h | ||
| 387 | dd imm | ||
| 388 | endm | ||
| 389 | |||
| 390 | CMP_EDX_ macro imm | ||
| 391 | db 66h,81h,0FAh | ||
| 392 | dd imm | ||
| 393 | endm | ||
| 394 | |||
| 395 | ; *** New Segment Register/AX moves *** | ||
| 396 | |||
| 397 | MOV_FS_AX macro | ||
| 398 | db 8Eh,0E0h | ||
| 399 | endm | ||
| 400 | |||
| 401 | MOV_AX_FS macro | ||
| 402 | db 8Ch,0E0h | ||
| 403 | endm | ||
| 404 | |||
| 405 | MOV_GS_AX macro | ||
| 406 | db 8Eh,0E8h | ||
| 407 | endm | ||
| 408 | |||
| 409 | MOV_AX_GS macro | ||
| 410 | db 8Ch,0E8h | ||
| 411 | endm | ||
| 412 | |||
| 413 | ; *** New Segment Register pushes & pops *** | ||
| 414 | |||
| 415 | PUSH_FS macro | ||
| 416 | db 0Fh,0A0h | ||
| 417 | endm | ||
| 418 | |||
| 419 | PUSH_GS macro | ||
| 420 | db 0Fh,0A8h | ||
| 421 | endm | ||
| 422 | |||
| 423 | POP_FS macro | ||
| 424 | db 0Fh,0A1h | ||
| 425 | endm | ||
| 426 | |||
| 427 | POP_GS macro | ||
| 428 | db 0Fh,0A9h | ||
| 429 | endm | ||
| 430 | |||
| 431 | ; *** New Segment Register offset 16 memory moves *** | ||
| 432 | |||
| 433 | MOV_off16_FS macro off16 | ||
| 434 | db 8Ch,26h | ||
| 435 | dw off16 | ||
| 436 | endm | ||
| 437 | |||
| 438 | MOV_FS_off16 macro off16 | ||
| 439 | db 8Eh,26h | ||
| 440 | dw off16 | ||
| 441 | endm | ||
| 442 | |||
| 443 | MOV_off16_GS macro off16 | ||
| 444 | db 8Ch,2Eh | ||
| 445 | dw off16 | ||
| 446 | endm | ||
| 447 | |||
| 448 | MOV_GS_off16 macro off16 | ||
| 449 | db 8Eh,2Eh | ||
| 450 | dw off16 | ||
| 451 | endm | ||
| 452 | |||
| 453 | ; *** General Register 32 bit pushes & pops *** | ||
| 454 | |||
| 455 | PUSH_EAX macro | ||
| 456 | db 66h | ||
| 457 | push ax | ||
| 458 | endm | ||
| 459 | |||
| 460 | POP_EAX macro | ||
| 461 | db 66h | ||
| 462 | pop ax | ||
| 463 | endm | ||
| 464 | |||
| 465 | PUSH_EBX macro | ||
| 466 | db 66h | ||
| 467 | push bx | ||
| 468 | endm | ||
| 469 | |||
| 470 | POP_EBX macro | ||
| 471 | db 66h | ||
| 472 | pop bx | ||
| 473 | endm | ||
| 474 | |||
| 475 | PUSH_ECX macro | ||
| 476 | db 66h | ||
| 477 | push cx | ||
| 478 | endm | ||
| 479 | |||
| 480 | POP_ECX macro | ||
| 481 | db 66h | ||
| 482 | pop cx | ||
| 483 | endm | ||
| 484 | |||
| 485 | PUSH_EDX macro | ||
| 486 | db 66h | ||
| 487 | push dx | ||
| 488 | endm | ||
| 489 | |||
| 490 | POP_EDX macro | ||
| 491 | db 66h | ||
| 492 | pop dx | ||
| 493 | endm | ||
| 494 | |||
| 495 | PUSH_EDI macro | ||
| 496 | db 66h | ||
| 497 | push di | ||
| 498 | endm | ||
| 499 | |||
| 500 | POP_EDI macro | ||
| 501 | db 66h | ||
| 502 | pop di | ||
| 503 | endm | ||
| 504 | |||
| 505 | PUSH_ESI macro | ||
| 506 | db 66h | ||
| 507 | push si | ||
| 508 | endm | ||
| 509 | |||
| 510 | POP_ESI macro | ||
| 511 | db 66h | ||
| 512 | pop si | ||
| 513 | endm | ||
| 514 | |||
| 515 | PUSH_EBP macro | ||
| 516 | db 66h | ||
| 517 | push bp | ||
| 518 | endm | ||
| 519 | |||
| 520 | POP_EBP macro | ||
| 521 | db 66h | ||
| 522 | pop bp | ||
| 523 | endm | ||
| 524 | |||
| 525 | PUSH_ESP macro | ||
| 526 | db 66h | ||
| 527 | push sp | ||
| 528 | endm | ||
| 529 | |||
| 530 | POP_ESP macro | ||
| 531 | db 66h | ||
| 532 | pop sp | ||
| 533 | endm | ||
| 534 | |||
| 535 | |||
| 536 | ; *** General Register 32 bit xors *** | ||
| 537 | |||
| 538 | XOR_EAX_EAX macro | ||
| 539 | db 66h | ||
| 540 | xor ax, ax | ||
| 541 | endm | ||
| 542 | |||
| 543 | XOR_EBX_EBX macro | ||
| 544 | db 66h | ||
| 545 | xor bx, bx | ||
| 546 | endm | ||
| 547 | |||
| 548 | XOR_ECX_ECX macro | ||
| 549 | db 66h | ||
| 550 | xor cx, cx | ||
| 551 | endm | ||
| 552 | |||
| 553 | XOR_EDX_EDX macro | ||
| 554 | db 66h | ||
| 555 | xor dx, dx | ||
| 556 | endm | ||
| 557 | |||
| 558 | XOR_EBP_EBP macro | ||
| 559 | db 66h | ||
| 560 | xor bp, bp | ||
| 561 | endm | ||
| 562 | |||
| 563 | .list ; end of INSTR386.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/IOTRAP.ASM b/v4.0/src/MEMM/MEMM/IOTRAP.ASM new file mode 100644 index 0000000..eb7d79c --- /dev/null +++ b/v4.0/src/MEMM/MEMM/IOTRAP.ASM | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title IOTRAP.ASM - Dispatches I/O trap handlers | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: IOTRAP.ASM - Dispatches I/O trap handlers | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: July 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 07/01/86 0.03 From ELIMTRAP.ASM | ||
| 27 | ; 07/03/86 0.03 Added handlers for 84,85,60, & 64 | ||
| 28 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ; | ||
| 32 | ; Functional Description: | ||
| 33 | ; | ||
| 34 | ; This routine is called by all I/O space trap handlers to allow | ||
| 35 | ; emulation/monitoring of I/O address reads and writes. When a GP fault | ||
| 36 | ; occurs due to I/O to an address trapped in the I/O Bit Map, the I/O | ||
| 37 | ; instruction emulation routine in VMINST calls this routine. This | ||
| 38 | ; routine calls the appropriate I/O trap handler for the I/O address. | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | .lfcond ; list false conditionals | ||
| 42 | .386p | ||
| 43 | page | ||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; P U B L I C D E C L A R A T I O N S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | public IO_Trap ; dispatches I/O trap handlers | ||
| 50 | |||
| 51 | ;****************************************************************************** | ||
| 52 | ; L O C A L C O N S T A N T S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | FALSE equ 0 | ||
| 56 | TRUE equ not FALSE | ||
| 57 | |||
| 58 | include VDMseg.inc | ||
| 59 | include VDMsel.inc | ||
| 60 | |||
| 61 | ;****************************************************************************** | ||
| 62 | ; E X T E R N A L R E F E R E N C E S | ||
| 63 | ;****************************************************************************** | ||
| 64 | |||
| 65 | _TEXT segment | ||
| 66 | |||
| 67 | extrn IOTrap_Tab:word ; System board IO trap routine address table | ||
| 68 | extrn IOT_BadT:near ; Routine to execute for unknown port | ||
| 69 | ;extrn IOT_LIM:near ; Routine to handle LIM emulated ports | ||
| 70 | extrn IOT_OEM:near ; Routine to handle OEM specific emulate ports | ||
| 71 | |||
| 72 | _TEXT ends | ||
| 73 | |||
| 74 | ;****************************************************************************** | ||
| 75 | ; S E G M E N T D E F I N I T I O N | ||
| 76 | ;****************************************************************************** | ||
| 77 | |||
| 78 | _TEXT segment | ||
| 79 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 80 | |||
| 81 | ;****************************************************************************** | ||
| 82 | ; IO_Trap - Dispatches trap handler for an I/O address | ||
| 83 | ; | ||
| 84 | ; ENTRY: Protected Mode Ring 0 | ||
| 85 | ; AL = byte to output to port. | ||
| 86 | ; DX = port address for I/O. | ||
| 87 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 88 | ; BX = 0 => Emulate Input. | ||
| 89 | ; <>0 => Emulate Output. | ||
| 90 | ; | ||
| 91 | ; EXIT: Protected Mode Ring 0 | ||
| 92 | ; AL = emulated input value from port. | ||
| 93 | ; CLC => I/O emulated by LIM_Trap. | ||
| 94 | ; STC => I/O NOT emulated by LIM_Trap. | ||
| 95 | ; | ||
| 96 | ; WARNING:*********** | ||
| 97 | ; This routine is closely allied with IOTBadT which is in TrapDef. | ||
| 98 | ; IOTBadT assumes that the stack is in a certain state! | ||
| 99 | ; *********** | ||
| 100 | ; | ||
| 101 | ; | ||
| 102 | ; USED: Flags | ||
| 103 | ; STACK: | ||
| 104 | ;------------------------------------------------------------------------------ | ||
| 105 | IO_Trap proc near | ||
| 106 | ; | ||
| 107 | push ds | ||
| 108 | push dx | ||
| 109 | |||
| 110 | push VDMD_GSEL | ||
| 111 | pop ds ; set DS = DGROUP | ||
| 112 | |||
| 113 | cmp dx,0100h ;Q: I/O Addr < 0100h (system brd port)? | ||
| 114 | jae IOT_NotSys ; N: check mapping regs | ||
| 115 | IOT_Sys: ; Y: dispatch I/O trap handler | ||
| 116 | xchg bx, dx ; BL = port address | ||
| 117 | shl bx,1 ; BX = BX*2 (word table) | ||
| 118 | call cs:IOTrap_Tab[bx] ; call handler | ||
| 119 | ; ENTRY: entry DX,DS on stack | ||
| 120 | ; DS = DGROUP selector | ||
| 121 | ; BX = 2 * port address in 0100h range | ||
| 122 | ; DX = input/output flag | ||
| 123 | |||
| 124 | xchg bx,dx ; reset bx | ||
| 125 | pop dx ; | ||
| 126 | pop ds ; reset dx | ||
| 127 | ret ; CF = 1 if I/O not emulated | ||
| 128 | |||
| 129 | ; | ||
| 130 | ; Address >= 0100h | ||
| 131 | |||
| 132 | IOT_NotSys: | ||
| 133 | ; | ||
| 134 | ; check for OEM specific I/O emulation | ||
| 135 | ; | ||
| 136 | call IOT_OEM ;If emulated by OEM specific routine | ||
| 137 | ; does not return(returns from IO_Trap) | ||
| 138 | ; NOTE : we don't have LIM h/w port anymore | ||
| 139 | ; | ||
| 140 | ; check for LIM mapping register address | ||
| 141 | ; | ||
| 142 | ; call IOT_LIM ;If emulated by LIM emulation routine | ||
| 143 | ; does not return(returns from IO_Trap) | ||
| 144 | |||
| 145 | ; | ||
| 146 | ; Here if I/O Address >= 0100h and not a mapping register | ||
| 147 | ; map it into 1k and try system board ports again | ||
| 148 | ; | ||
| 149 | and dx,3FFh ; map address into 1k range | ||
| 150 | cmp dx,0100h ;Q: I/O Addr < 0100h (system brd port)? | ||
| 151 | jb IOT_Sys ; Y: check system ports | ||
| 152 | ; N: unknown port | ||
| 153 | xchg bx,dx ; put Input/Output flag in DX for IOT_BadT | ||
| 154 | shl bx,1 | ||
| 155 | call IOT_BadT | ||
| 156 | jmp $ ;IOT_BadT pops return address off restores regs | ||
| 157 | ; and returns | ||
| 158 | |||
| 159 | IO_Trap endp | ||
| 160 | |||
| 161 | |||
| 162 | _TEXT ends | ||
| 163 | |||
| 164 | end | ||
| 165 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/KBD.ASM b/v4.0/src/MEMM/MEMM/KBD.ASM new file mode 100644 index 0000000..3616c1e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/KBD.ASM | |||
| @@ -0,0 +1,1608 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title KBD.ASM - - protected mode AT keyboard driver | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMMD.EXE - MICROSOFT Expanded Memory Manager 386 DEBUG Driver | ||
| 11 | ; | ||
| 12 | ; Module: KBD.ASM - - protected mode AT keyboard driver for debugger | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; A- Removed STIs and changed CLI/STIs to keep interrupt | ||
| 28 | ; status stable (OFF) during debugger execution. The | ||
| 29 | ; specific problem was in reporting unexpected traps | ||
| 30 | ; fielded from Virtual Mode during DOS execution, | ||
| 31 | ; e.g. timer ticks. | ||
| 32 | ; B- Fixed Ctrl-NumLock, Ctrl-Alt-Del, Ctrl-Break, and | ||
| 33 | ; Shift-PrtSc | ||
| 34 | ; 05/12/86 C Cleanup and segment reorganization | ||
| 35 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 36 | ; 07/05/86 0.04 Moved to DCODE segment | ||
| 37 | ; | ||
| 38 | ;****************************************************************************** | ||
| 39 | ; | ||
| 40 | ; Functional Description: | ||
| 41 | ; | ||
| 42 | ; THIS CODE IS USED BY THE DEBUGGER ONLY ! | ||
| 43 | ; | ||
| 44 | ; This is a PC/AT keyboard driver capable of running | ||
| 45 | ; in protected mode. It does not require any ROM support. | ||
| 46 | ; | ||
| 47 | ; The major modifications are: | ||
| 48 | ; | ||
| 49 | ; - Remove foreign tables, use US only | ||
| 50 | ; - Hard code machine type rather than looking in ROM | ||
| 51 | ; - hard code BeepFreq, BeepDur | ||
| 52 | ; - removed KeyVector, put read-only data in CS | ||
| 53 | ; - removed Accent stuff, which had code writes | ||
| 54 | ; - removed code writes in foreign kbd | ||
| 55 | ; - removed INT 15h sysreq and post | ||
| 56 | ; - removed T&SR stuff, added buffer read routine "getc" | ||
| 57 | ; - made it polled, removed all interrupt stuff | ||
| 58 | ; - changed "data" segment to "romdata" | ||
| 59 | ; | ||
| 60 | ; | ||
| 61 | ; SCCSID = @(#)keybxx.asm 4.1 85/10/09 | ||
| 62 | ;------------------------------------------------------ | ||
| 63 | ; | ||
| 64 | ; KEYBXX - foreign keyboard driver. | ||
| 65 | ; | ||
| 66 | ; April 1985 by Michael Hanson | ||
| 67 | ; Copyright 1985 by Microsoft Corporation | ||
| 68 | ; | ||
| 69 | ; KeybXX is a keyboard handling program using tables | ||
| 70 | ; supplied in a separate file to do foreign language | ||
| 71 | ; keyboard support. It is the basis for the KEYB??.EXE | ||
| 72 | ; programs which use this program and the corresponding | ||
| 73 | ; table defined in KEYB??.ASM. | ||
| 74 | ; | ||
| 75 | ; KeybXX.OBJ must be linked with one of the Keyb??.OBJ | ||
| 76 | ; programs to work, the KEYB?? file must be first. | ||
| 77 | ; See the accompanying makefile for examples. | ||
| 78 | ; | ||
| 79 | ; Note: KEYB?? refers to any of KEYBFR ( French ), | ||
| 80 | ; KEYBGR (German), KEYBUK (United Kingdom), | ||
| 81 | ; KEYBIT (Italian), KEYBSP (Spanish) and | ||
| 82 | ; KEYBDV (Dvorak). These are the currently | ||
| 83 | ; defined data tables for KEYBXX. | ||
| 84 | ; | ||
| 85 | ; Compatability notes: | ||
| 86 | ; 1. The IBM foreign keyboard drivers don't return | ||
| 87 | ; anything for a CTRL-ALT space. This is not | ||
| 88 | ; what I expect from the manuals, but for | ||
| 89 | ; compatibility, KEYBXX doesn't return anything | ||
| 90 | ; in this case either. | ||
| 91 | ; | ||
| 92 | ; 2. For the AT the keyboard driver should do a post | ||
| 93 | ; call (int 15). The ROM keyboard driver does, but | ||
| 94 | ; IBM's foreign keyboard drivers appear not to. | ||
| 95 | ; Currently KEYBXX does a post code, though only | ||
| 96 | ; one is issued at any one time (that is, only 1 post | ||
| 97 | ; call for the 2 characters returned by an illegal | ||
| 98 | ; accent combination). | ||
| 99 | ; | ||
| 100 | ; This program is a modified version of the keyboard handler from - | ||
| 101 | ; | ||
| 102 | ; Microsoft Mach 10 Enhancement Software | ||
| 103 | ; | ||
| 104 | ; Copyright 1984 by Microsoft Corporation | ||
| 105 | ; Written June 1984 by Chris Peters | ||
| 106 | ; | ||
| 107 | ;****************************************************************************** | ||
| 108 | .lfcond ; list false conditionals | ||
| 109 | .386p | ||
| 110 | |||
| 111 | include VDMseg.inc | ||
| 112 | include desc.inc | ||
| 113 | include kbd.inc | ||
| 114 | |||
| 115 | |||
| 116 | MASTER_IMR equ 21h ; mask port for master 8259 | ||
| 117 | |||
| 118 | ;*** ROM BIOS data area, set up addresses | ||
| 119 | romdata segment use16 at 40h | ||
| 120 | org 17h | ||
| 121 | KeyState db ? | ||
| 122 | BreakState db ? | ||
| 123 | AltKey db ? | ||
| 124 | KbHead dw ? | ||
| 125 | KbTail dw ? | ||
| 126 | KbBuffer dw 16 dup (?) | ||
| 127 | KbBufferEnd label word | ||
| 128 | |||
| 129 | org 49h | ||
| 130 | VidMode db ? | ||
| 131 | org 65h | ||
| 132 | VidReg db ? | ||
| 133 | |||
| 134 | org 71h | ||
| 135 | fBreak db ? | ||
| 136 | fReset dw ? | ||
| 137 | |||
| 138 | org 80h | ||
| 139 | KbStart dw ? | ||
| 140 | KbEnd dw ? | ||
| 141 | |||
| 142 | org 97h | ||
| 143 | ATKbFlags db ? | ||
| 144 | romdata ends | ||
| 145 | |||
| 146 | |||
| 147 | |||
| 148 | ;*** Routines used by data table modules (Keyb??) | ||
| 149 | public SpecKey | ||
| 150 | public AlphaKey | ||
| 151 | public NormalKey | ||
| 152 | public Keys$2$13 | ||
| 153 | public CapKey | ||
| 154 | public Cap$2$13 | ||
| 155 | public FuncKey | ||
| 156 | public PadKey | ||
| 157 | public NumKey | ||
| 158 | public SpaceKey | ||
| 159 | public ShiftKey | ||
| 160 | public ScrollKey | ||
| 161 | public StateKey | ||
| 162 | ;public AccKey | ||
| 163 | public AltShiftKey | ||
| 164 | public BufferFull | ||
| 165 | public ReBoot | ||
| 166 | public XBoot | ||
| 167 | public PrintScreen | ||
| 168 | public SysReq | ||
| 169 | |||
| 170 | |||
| 171 | |||
| 172 | |||
| 173 | DCODE segment | ||
| 174 | assume cs:DCODE,ds:romdata,es:nothing | ||
| 175 | |||
| 176 | |||
| 177 | ;*** Tables for foreign language key layout | ||
| 178 | ; See Keyb?? files for more details | ||
| 179 | |||
| 180 | |||
| 181 | ;* Actual foreign language key layout | ||
| 182 | ; extrn ForeignTable :word | ||
| 183 | |||
| 184 | |||
| 185 | ;* Tables to map CNTRL ALT char | ||
| 186 | ; extrn AltChrs :byte | ||
| 187 | AltChrs label byte | ||
| 188 | ; extrn AltChrsEnd :byte | ||
| 189 | AltChrsEnd label byte | ||
| 190 | |||
| 191 | ; extrn AltMap :byte | ||
| 192 | AltMap label byte | ||
| 193 | |||
| 194 | |||
| 195 | ;* Tables to map accented characters | ||
| 196 | ; extrn AccentChTbl :word | ||
| 197 | AccentChTbl label word | ||
| 198 | |||
| 199 | ; extrn AccentMpTbl :word | ||
| 200 | AccentMpTbl label word | ||
| 201 | |||
| 202 | |||
| 203 | ;* Table of accent characters, shifted, ALTed and CTRLed. | ||
| 204 | ; defined using the AccChStruc struct | ||
| 205 | ; extrn AccChTbl :word | ||
| 206 | AccChTbl label word | ||
| 207 | |||
| 208 | |||
| 209 | |||
| 210 | ;*** Internal variables used by KEYBXX interrupt handler | ||
| 211 | ; KeyVector dd ? ; origin of keyboard decode table | ||
| 212 | ;PCType db ? ; type of PC running on | ||
| 213 | PCType db 0fch ; type of PC running on | ||
| 214 | |||
| 215 | PC_AT = 0FCh ;if anything else, assume PC/XT | ||
| 216 | |||
| 217 | ;Accent db 0 ; set for accent key, =0 for none. | ||
| 218 | ;AccentKey dw ? ; last accent key pressed | ||
| 219 | |||
| 220 | ; BeepFreq dw PCBeepFreq ;Count for beep half-cycle | ||
| 221 | BeepFreq dw ATBeepFreq ;Count for beep half-cycle | ||
| 222 | ; BeepDur dw PCBeepDur ;Count of half-cycles to beep | ||
| 223 | BeepDur dw ATBeepDur ;Count of half-cycles to beep | ||
| 224 | |||
| 225 | |||
| 226 | ;*** Normal keyboard table, used in CTRL-ALT F1 mode | ||
| 227 | ; | ||
| 228 | ; See Keyb?? files for structure information. | ||
| 229 | ; | ||
| 230 | ForeignTable label word | ||
| 231 | KeyMapTable label word | ||
| 232 | public KeyMapTable | ||
| 233 | |||
| 234 | db 0,0 ;0 | ||
| 235 | dw BufferFull | ||
| 236 | db esc,esc ;1 | ||
| 237 | dw SpecKey | ||
| 238 | db "1","!" ;2 | ||
| 239 | dw Keys$2$13 | ||
| 240 | db "2","@" ;3 | ||
| 241 | dw Keys$2$13 | ||
| 242 | db "3","#" ;4 | ||
| 243 | dw Keys$2$13 | ||
| 244 | db "4","$" ;5 | ||
| 245 | dw Keys$2$13 | ||
| 246 | db "5","%" ;6 | ||
| 247 | dw Keys$2$13 | ||
| 248 | db "6","^" ;7 | ||
| 249 | dw Keys$2$13 | ||
| 250 | db "7","&" ;8 | ||
| 251 | dw Keys$2$13 | ||
| 252 | db "8","*" ;9 | ||
| 253 | dw Keys$2$13 | ||
| 254 | db "9","(" ;10 | ||
| 255 | dw Keys$2$13 | ||
| 256 | db "0",")" ;11 | ||
| 257 | dw Keys$2$13 | ||
| 258 | db "-","_" ;12 | ||
| 259 | dw Keys$2$13 | ||
| 260 | db "=","+" ;13 | ||
| 261 | dw Keys$2$13 | ||
| 262 | db 8,127 ;14 | ||
| 263 | dw SpecKey | ||
| 264 | db 9,0 ;15 | ||
| 265 | dw NormalKey | ||
| 266 | db "q","Q" ;16 | ||
| 267 | dw AlphaKey | ||
| 268 | db "w","W" ;17 | ||
| 269 | dw AlphaKey | ||
| 270 | db "e","E" ;18 | ||
| 271 | dw AlphaKey | ||
| 272 | db "r","R" ;19 | ||
| 273 | dw AlphaKey | ||
| 274 | db "t","T" ;20 | ||
| 275 | dw AlphaKey | ||
| 276 | db "y","Y" ;21 | ||
| 277 | dw AlphaKey | ||
| 278 | db "u","U" ;22 | ||
| 279 | dw AlphaKey | ||
| 280 | db "i","I" ;23 | ||
| 281 | dw AlphaKey | ||
| 282 | db "o","O" ;24 | ||
| 283 | dw AlphaKey | ||
| 284 | db "p","P" ;25 | ||
| 285 | dw AlphaKey | ||
| 286 | db "[","{" ;26 | ||
| 287 | dw NormalKey | ||
| 288 | db "]","}" ;27 | ||
| 289 | dw NormalKey | ||
| 290 | db 13,10 ;28 | ||
| 291 | dw SpecKey | ||
| 292 | db CtrlShift,(255-CtrlShift) | ||
| 293 | dw ShiftKey | ||
| 294 | db "a","A" ;30 | ||
| 295 | dw AlphaKey | ||
| 296 | db "s","S" ;31 | ||
| 297 | dw AlphaKey | ||
| 298 | db "d","D" ;32 | ||
| 299 | dw AlphaKey | ||
| 300 | db "f","F" ;33 | ||
| 301 | dw AlphaKey | ||
| 302 | db "g","G" ;34 | ||
| 303 | dw AlphaKey | ||
| 304 | db "h","H" ;35 | ||
| 305 | dw AlphaKey | ||
| 306 | db "j","J" ;36 | ||
| 307 | dw AlphaKey | ||
| 308 | db "k","K" ;37 | ||
| 309 | dw AlphaKey | ||
| 310 | db "l","L" ;38 | ||
| 311 | dw AlphaKey | ||
| 312 | db ";",":" ;39 | ||
| 313 | dw NormalKey | ||
| 314 | db "'",'"' ;40 | ||
| 315 | dw NormalKey | ||
| 316 | db "`","~" ;41 | ||
| 317 | dw NormalKey | ||
| 318 | db LeftShift,(255-LeftShift) | ||
| 319 | dw ShiftKey | ||
| 320 | db "\","|" ;43 | ||
| 321 | dw NormalKey | ||
| 322 | db "z","Z" ;44 | ||
| 323 | dw AlphaKey | ||
| 324 | db "x","X" ;45 | ||
| 325 | dw AlphaKey | ||
| 326 | db "c","C" ;46 | ||
| 327 | dw AlphaKey | ||
| 328 | db "v","V" ;47 | ||
| 329 | dw AlphaKey | ||
| 330 | db "b","B" ;48 | ||
| 331 | dw AlphaKey | ||
| 332 | db "n","N" ;49 | ||
| 333 | dw AlphaKey | ||
| 334 | db "m","M" ;50 | ||
| 335 | dw AlphaKey | ||
| 336 | db ",","<" ;51 | ||
| 337 | dw NormalKey | ||
| 338 | db ".",">" ;52 | ||
| 339 | dw NormalKey | ||
| 340 | db "/","?" ;53 | ||
| 341 | dw NormalKey | ||
| 342 | db RightShift,(255-RightShift) | ||
| 343 | dw ShiftKey | ||
| 344 | db "*",114 ;55 | ||
| 345 | dw PrintScreen | ||
| 346 | db AltShift,(255-AltShift) ;56 | ||
| 347 | dw AltShiftKey | ||
| 348 | db " "," " ;57 | ||
| 349 | dw SpaceKey | ||
| 350 | db CapsState,(255-CapsState) | ||
| 351 | dw StateKey | ||
| 352 | db 1,1 ;59 | ||
| 353 | dw FuncKey | ||
| 354 | db 2,2 ;60 | ||
| 355 | dw FuncKey | ||
| 356 | db 3,3 ;61 | ||
| 357 | dw FuncKey | ||
| 358 | db 4,4 ;62 | ||
| 359 | dw FuncKey | ||
| 360 | db 5,5 ;63 | ||
| 361 | dw FuncKey | ||
| 362 | db 6,6 ;64 | ||
| 363 | dw FuncKey | ||
| 364 | db 7,7 ;65 | ||
| 365 | dw FuncKey | ||
| 366 | db 8,8 ;66 | ||
| 367 | dw FuncKey | ||
| 368 | db 9,9 ;67 | ||
| 369 | dw FuncKey | ||
| 370 | db 0,0 ;68 | ||
| 371 | dw FuncKey | ||
| 372 | db NumState,(255-NumState) ;69 | ||
| 373 | dw NumKey | ||
| 374 | db ScrollState,(255-ScrollState) | ||
| 375 | dw ScrollKey | ||
| 376 | db 0,"7" ;71 | ||
| 377 | dw PadKey | ||
| 378 | db 1,"8" ;72 | ||
| 379 | dw PadKey | ||
| 380 | db 2,"9" ;73 | ||
| 381 | dw PadKey | ||
| 382 | db 3,"-" ;74 | ||
| 383 | dw PadKey | ||
| 384 | db 4,"4" ;75 | ||
| 385 | dw PadKey | ||
| 386 | db 5,"5" ;76 | ||
| 387 | dw PadKey | ||
| 388 | db 6,"6" ;77 | ||
| 389 | dw PadKey | ||
| 390 | db 7,"+" ;78 | ||
| 391 | dw PadKey | ||
| 392 | db 8,"1" ;79 | ||
| 393 | dw PadKey | ||
| 394 | db 9,"2" ;80 | ||
| 395 | dw PadKey | ||
| 396 | db 10,"3" ;81 | ||
| 397 | dw PadKey | ||
| 398 | db 11,"0" ;82 | ||
| 399 | dw PadKey | ||
| 400 | db 12,"." ;83 | ||
| 401 | dw ReBoot | ||
| 402 | db 0, 0 ;84 (On AT only) | ||
| 403 | dw SysReq | ||
| 404 | |||
| 405 | |||
| 406 | |||
| 407 | ;*** Tables for keypad with ALT and control | ||
| 408 | ; Same for foreign as normal | ||
| 409 | AltKeyPad label byte | ||
| 410 | db 7,8,9,-1 | ||
| 411 | db 4,5,6,-1 | ||
| 412 | db 1,2,3 | ||
| 413 | db 0,-1 | ||
| 414 | |||
| 415 | CtrlKeyPad label byte | ||
| 416 | db 119,-1,132,-1 | ||
| 417 | db 115,-1,116,-1 | ||
| 418 | db 117,-1,118 | ||
| 419 | db -1,-1 | ||
| 420 | |||
| 421 | |||
| 422 | |||
| 423 | ;*** Table for ALT alphabetical character | ||
| 424 | ; | ||
| 425 | ; Since uses alpha char as index, this is the same | ||
| 426 | ; for normal and foreign keyboards. | ||
| 427 | ; | ||
| 428 | AltTable label byte | ||
| 429 | ; a, b, c, d, e, f, g, h, i, j, k, l, m | ||
| 430 | db 30,48,46,32,18,33,34,35,23,36,37,38,50 | ||
| 431 | ; n, o, p, q, r, s, t, u, v, w, x, y, z | ||
| 432 | db 49,24,25,16,19,31,20,22,47,17,45,21,44 | ||
| 433 | |||
| 434 | |||
| 435 | |||
| 436 | SUBTTL Keyboard Interrupt Handler | ||
| 437 | |||
| 438 | |||
| 439 | ;*** Keyboard interrupt handler | ||
| 440 | ; | ||
| 441 | handler proc near | ||
| 442 | |||
| 443 | KbInt: | ||
| 444 | ;* sti | ||
| 445 | cld | ||
| 446 | push ax | ||
| 447 | push bx | ||
| 448 | push cx | ||
| 449 | push dx | ||
| 450 | push si | ||
| 451 | push di | ||
| 452 | push ds | ||
| 453 | push es | ||
| 454 | |||
| 455 | ; First see if there is any data in the kbd buffer. | ||
| 456 | ; Return to caller if not. | ||
| 457 | |||
| 458 | in al, KbStatus | ||
| 459 | test al, 1 | ||
| 460 | jnz intr1 | ||
| 461 | jmp RestoreRegs | ||
| 462 | intr1: | ||
| 463 | |||
| 464 | mov ax,romdata | ||
| 465 | mov ds,ax | ||
| 466 | call GetSCode ;Get scan code from keyboard in al | ||
| 467 | mov ah,al ;(ah) = scan code | ||
| 468 | cmp al,-1 | ||
| 469 | jnz KbI1 | ||
| 470 | jmp BufferFull ;go handle overrun code | ||
| 471 | KbI1: | ||
| 472 | mov bx,ax | ||
| 473 | and bx,7fh ;(bl) = scan code without break bit | ||
| 474 | cmp bl,84 | ||
| 475 | jle KBI2 | ||
| 476 | jmp KeyRet ;ignore code if not in range | ||
| 477 | KBI2: | ||
| 478 | shl bx,1 ;index into lookup table | ||
| 479 | shl bx,1 | ||
| 480 | ;* Check for CTRL-ALT chars | ||
| 481 | test ah, 80h ;no CTRL-ALT remap on break code | ||
| 482 | jnz KbI23 | ||
| 483 | ; cmp word ptr [KeyVector],offset KeyMapTable | ||
| 484 | ; je KbI23 ;Not foreign keyboard | ||
| 485 | jmp KbI23 | ||
| 486 | test [KeyState], CtrlShift | ||
| 487 | jz KbI23 | ||
| 488 | test [KeyState], AltShift | ||
| 489 | jz KbI23 | ||
| 490 | push ax ; save scan code | ||
| 491 | |||
| 492 | ;* map CTRL-ALT char | ||
| 493 | ; look up chars in table, if found then put out corresponding | ||
| 494 | ; entry from map table. | ||
| 495 | mov si, offset AltChrs - 1 ;Set up index to lookup | ||
| 496 | KbI21: | ||
| 497 | inc si ; Advance to next entry | ||
| 498 | cmp si, offset AltChrsEnd | ||
| 499 | jae KbI22 ;at end of table, so no remap | ||
| 500 | cmp ah, cs:[si] | ||
| 501 | jne KbI21 ;this isn't it so loop | ||
| 502 | ; Found character, so do the mapping | ||
| 503 | sub si, offset AltChrs | ||
| 504 | add si, offset AltMap ;get index into remaped table | ||
| 505 | pop ax ;get scan code | ||
| 506 | mov al, cs:[si] ;get new character to use | ||
| 507 | jmp PutKRet | ||
| 508 | KbI22: | ||
| 509 | pop ax | ||
| 510 | KbI23: | ||
| 511 | |||
| 512 | ; les si,[KeyVector] | ||
| 513 | mov si, offset KeyMapTable | ||
| 514 | mov cx,cs:[si+bx] ;(cx) = lc, uc bytes | ||
| 515 | mov al,cl ;(al) = lc code for key | ||
| 516 | mov dl,[KeyState] ;(dl) = keyboard flags | ||
| 517 | jmp word ptr cs:[si+bx+2] ;Call appropriate key handler | ||
| 518 | ;*** | ||
| 519 | ; for all key handler routines, | ||
| 520 | ; | ||
| 521 | ; (CX) = uc, lc code bytes from table | ||
| 522 | ; (DL) = keyboard flags byte (see equates above for bits) | ||
| 523 | ; (AL) = lc code from cl | ||
| 524 | ; (AH) = scan code from keyboard | ||
| 525 | |||
| 526 | handler endp | ||
| 527 | |||
| 528 | |||
| 529 | SUBTTL Key Routines | ||
| 530 | |||
| 531 | ;*** Key handling routines, called as specified by the key table | ||
| 532 | |||
| 533 | ;------------------------------------------------------ | ||
| 534 | ; | ||
| 535 | ; Alphabetical key, caps lock works as do CTRL and ALT | ||
| 536 | ; | ||
| 537 | AlphaKey: | ||
| 538 | call NoBreak | ||
| 539 | test dl,AltShift | ||
| 540 | jz ak1 | ||
| 541 | cbw | ||
| 542 | add bx,ax | ||
| 543 | mov ah,[AltTable+bx-"a"] | ||
| 544 | jmp MakeAlt | ||
| 545 | |||
| 546 | ak1: test dl,CtrlShift | ||
| 547 | jz ak2 | ||
| 548 | sub al,"a"-1 | ||
| 549 | jmp PutKRet | ||
| 550 | |||
| 551 | ak2: xor bh,bh | ||
| 552 | test dl,RightShift+LeftShift | ||
| 553 | jz ak3 | ||
| 554 | or bh,CapsState | ||
| 555 | ak3: mov cl,dl | ||
| 556 | and cl,CapsState | ||
| 557 | xor bh,cl | ||
| 558 | jz ak4 | ||
| 559 | mov al,ch | ||
| 560 | ak4: jmp PutKRet | ||
| 561 | |||
| 562 | |||
| 563 | ;------------------------------------------------------ | ||
| 564 | ; | ||
| 565 | ; Keys that do something different when CTRL is down | ||
| 566 | ; | ||
| 567 | SpecKey: | ||
| 568 | call NoAlt | ||
| 569 | test dl,CtrlShift | ||
| 570 | jz bsp1 | ||
| 571 | mov al,ch | ||
| 572 | bsp1: jmp PutKRet | ||
| 573 | |||
| 574 | |||
| 575 | ;----------------------------------------------------- | ||
| 576 | ; | ||
| 577 | ; Normal, Non Alphabetic key | ||
| 578 | ; | ||
| 579 | NormalKey: ;These return nothing on ALT | ||
| 580 | call NoAlt | ||
| 581 | test dl,CtrlShift | ||
| 582 | jz nk0 | ||
| 583 | jmp short Ca20 ;ky21 | ||
| 584 | |||
| 585 | Keys$2$13: ;Keys #2 - 13 have ALT codes 120,... | ||
| 586 | call NoBreak | ||
| 587 | test dl,AltShift | ||
| 588 | jz Ky2 | ||
| 589 | add ah,120-2 | ||
| 590 | jmp MakeAlt | ||
| 591 | |||
| 592 | ky2: test dl,CtrlShift | ||
| 593 | jnz Ca20 ;handle CTRL key same as for CapKey | ||
| 594 | nk0: | ||
| 595 | test dl,RightShift+LeftShift | ||
| 596 | jz nk1 | ||
| 597 | mov al,ch | ||
| 598 | nk1: jmp PutKRet | ||
| 599 | |||
| 600 | |||
| 601 | ;----------------------------------------------------- | ||
| 602 | ; | ||
| 603 | ; Non Alphabetic key for which cap lock works | ||
| 604 | ; | ||
| 605 | CapKey: ; CAPLOCK works, ALT doesn't | ||
| 606 | call NoAlt | ||
| 607 | test dl,CtrlShift | ||
| 608 | jz ca5 | ||
| 609 | jmp short ca20 ;ca3 | ||
| 610 | |||
| 611 | Cap$2$13: ; KEYS 2-13 with CAPLOCK working | ||
| 612 | call NoBreak | ||
| 613 | test dl,AltShift | ||
| 614 | jz ca2 | ||
| 615 | add ah,120-2 | ||
| 616 | jmp MakeAlt | ||
| 617 | |||
| 618 | ca2: test dl,CtrlShift | ||
| 619 | jz ca5 | ||
| 620 | ca20: cmp ah, 3 ;Keep CTRL keys at same scan code locations | ||
| 621 | jnz ca21 | ||
| 622 | jmp MakeAlt | ||
| 623 | ca21: cmp ah, 7 | ||
| 624 | jnz ca22 | ||
| 625 | mov al, 30 | ||
| 626 | jmp short ca7 | ||
| 627 | ca22: cmp ah, 26 | ||
| 628 | jnz ca23 | ||
| 629 | mov al, 27 | ||
| 630 | jmp short ca7 | ||
| 631 | ca23: cmp ah, 27 | ||
| 632 | jnz ca24 | ||
| 633 | mov al, 29 | ||
| 634 | jmp short ca7 | ||
| 635 | ca24: | ||
| 636 | cmp ah, 43 | ||
| 637 | jnz ca25 | ||
| 638 | mov al, 28 | ||
| 639 | jmp short ca7 | ||
| 640 | ca25: cmp al, '-' ;Except for - key, which moves around. | ||
| 641 | jnz ca26 | ||
| 642 | mov al, 31 | ||
| 643 | jmp short ca7 | ||
| 644 | ca26: jmp KeyRet | ||
| 645 | |||
| 646 | |||
| 647 | ca5: xor bh,bh | ||
| 648 | test dl,RightShift+LeftShift | ||
| 649 | jz ca6 | ||
| 650 | or bh,CapsState | ||
| 651 | ca6: mov cl,dl | ||
| 652 | and cl,CapsState | ||
| 653 | xor bh,cl | ||
| 654 | jz ca7 | ||
| 655 | mov al,ch | ||
| 656 | ca7: jmp PutKRet | ||
| 657 | |||
| 658 | |||
| 659 | ;--------------------------------------------------- | ||
| 660 | ; | ||
| 661 | ; Scroll Lock, Caps Lock, Num Lock | ||
| 662 | ; | ||
| 663 | ScrollKey: | ||
| 664 | test ah,80h | ||
| 665 | jnz stk0 | ||
| 666 | test dl,CtrlShift | ||
| 667 | jz stk1 | ||
| 668 | mov ax,[KbStart] | ||
| 669 | mov [KbHead],ax | ||
| 670 | mov [KbTail],ax | ||
| 671 | mov [fBreak],80h | ||
| 672 | call EnableKB | ||
| 673 | ;*a int 1bh | ||
| 674 | ;*a xor ax,ax | ||
| 675 | mov ax,0003 ;*a simulate ^C | ||
| 676 | jmp PutKRet | ||
| 677 | |||
| 678 | NumKey: ; NUM LOCK key | ||
| 679 | test ah,80h | ||
| 680 | jnz stk0 | ||
| 681 | test dl,CtrlShift | ||
| 682 | jz stk1 | ||
| 683 | or [BreakState],HoldState ; CTRL NUMLOCK | ||
| 684 | call VideoOn | ||
| 685 | nlk1: | ||
| 686 | call handler ;*a (look for key since no interrupts) | ||
| 687 | test [BreakState],HoldState ; Wait for a key press | ||
| 688 | jnz nlk1 | ||
| 689 | jmp RestoreRegs | ||
| 690 | |||
| 691 | StateKey: ; Toggle key | ||
| 692 | test ah,80h | ||
| 693 | jz stk1 | ||
| 694 | stk0: and [BreakState],ch ; Indicate key no longer held down | ||
| 695 | jmp short shf4 | ||
| 696 | |||
| 697 | stk1: mov ah,al | ||
| 698 | and al,[BreakState] | ||
| 699 | jnz shf4 ; Ignore if key already down | ||
| 700 | or [BreakState],ah ; Indicate key held down | ||
| 701 | xor dl,ah ; Toggle bit for this key | ||
| 702 | jmp short shf3 ; And go store it. | ||
| 703 | |||
| 704 | |||
| 705 | ;--------------------------------------------------- | ||
| 706 | ; | ||
| 707 | ; Alt Shift | ||
| 708 | ; | ||
| 709 | AltShiftKey: | ||
| 710 | test ah,80h | ||
| 711 | jz shf2 ; Indicate that ALT key down | ||
| 712 | xor al,al | ||
| 713 | xchg al,[AltKey] ; Find numeric code entered | ||
| 714 | or al,al | ||
| 715 | jz shf1 ; Just reset indicator if none | ||
| 716 | and [KeyState],ch | ||
| 717 | xor ah,ah ; Make it a key with 0 scan code | ||
| 718 | jmp PutKRet | ||
| 719 | |||
| 720 | ;---------------------------------------------------- | ||
| 721 | ; | ||
| 722 | ; Shift, Ctrl | ||
| 723 | ; | ||
| 724 | ShiftKey: | ||
| 725 | test ah,80h | ||
| 726 | jz shf2 | ||
| 727 | shf1: and dl,ch ; Unset indicator bit for break code | ||
| 728 | jmp short shf3 | ||
| 729 | shf2: or dl,al ; Set indicator bit for make code | ||
| 730 | shf3: mov [KeyState],dl | ||
| 731 | shf4: jmp KeyRet | ||
| 732 | |||
| 733 | |||
| 734 | ;---------------------------------------------------- | ||
| 735 | ; | ||
| 736 | ; Reboot System? | ||
| 737 | ; | ||
| 738 | ReBoot: call NoBreak ; Del key pressed, check CTRL ALT DEL | ||
| 739 | test dl,AltShift | ||
| 740 | jz pdk2 | ||
| 741 | test dl,CtrlShift | ||
| 742 | jz pdkx | ||
| 743 | XBoot: ; Reboot system. | ||
| 744 | mov ax,romdata ; ds = romdata segment | ||
| 745 | mov ds,ax | ||
| 746 | mov [fReset],1234h | ||
| 747 | ;*a | ||
| 748 | ;*a 02/12/86 - use shutdown code 10 and [40:67] to return to real mode | ||
| 749 | ;*a and enter the ROM at the CTRL-ALT-DEL entry point | ||
| 750 | ;*a | ||
| 751 | cli ; make sure | ||
| 752 | mov al,0Fh or 80h ; shutdown byte address/disable NMI | ||
| 753 | out 70h,al ; write CMOS address | ||
| 754 | jmp short $+2 ; (delay) | ||
| 755 | mov al,0Ah ; Shutdown code 10 = jump [dword @40:67] | ||
| 756 | out 71h,al ; write shutdown code to shutdown byte | ||
| 757 | ; | ||
| 758 | ; Set up entry point after the reset | ||
| 759 | ; | ||
| 760 | mov ds:[67h],0EA81h ; offset of CTRL-ALT-DEL entry point | ||
| 761 | mov ds:[67h+2],0F000h ; segment of CTRL-ALT-DEL entry point | ||
| 762 | ; | ||
| 763 | ; Reset the CPU | ||
| 764 | ; | ||
| 765 | mov al,0FEh ; FEh = pulse output bit 0 (286 reset) | ||
| 766 | out 64h,al ; command to 8042 | ||
| 767 | hlt ; don't want to coast | ||
| 768 | ;*a | ||
| 769 | ;*a end inserted code | ||
| 770 | ;*a | ||
| 771 | ;*a mov ax,-1 | ||
| 772 | ;*a push ax | ||
| 773 | ;*a xor ax,ax | ||
| 774 | ;*a push ax | ||
| 775 | ;*a xxx proc far | ||
| 776 | ;*a ret ; To reboot system, do a far return to FFFFh:0 | ||
| 777 | ;*a xxx endp | ||
| 778 | |||
| 779 | |||
| 780 | ;---------------------------------------------------- | ||
| 781 | ; | ||
| 782 | ; Key Pad Key | ||
| 783 | ; | ||
| 784 | PadKey: | ||
| 785 | mov bl,[AltKey] | ||
| 786 | call NoBreak2 | ||
| 787 | test dl,AltShift | ||
| 788 | jz pdk2 ; Not entering a character number | ||
| 789 | xor bx,bx | ||
| 790 | mov bl,cl | ||
| 791 | mov cl,cs:AltKeyPad[bx] ; Get numeric value for this key | ||
| 792 | cmp cl,-1 | ||
| 793 | jz pdk0 ; Start over if non-digit key | ||
| 794 | mov al,10 | ||
| 795 | mul [AltKey] | ||
| 796 | add al,cl | ||
| 797 | jmp short pdk1 | ||
| 798 | pdk0: xor ax,ax | ||
| 799 | pdk1: mov [AltKey],al | ||
| 800 | pdkx: jmp KeyRet | ||
| 801 | |||
| 802 | pdk2: mov al,0 | ||
| 803 | test dl,CtrlShift | ||
| 804 | jz pdk3 | ||
| 805 | xor bx,bx ; Lookup CTRL keypad key code | ||
| 806 | mov bl,cl | ||
| 807 | mov ah,cs:CtrlKeyPad[bx] | ||
| 808 | jmp short pdk6 | ||
| 809 | pdk3: cmp ah,74 ; - key independent of shift state | ||
| 810 | jz pdk41 | ||
| 811 | cmp ah,78 ; + key independent of shift state | ||
| 812 | jz pdk41 | ||
| 813 | xor bx,bx | ||
| 814 | test dl,RightShift+LeftShift | ||
| 815 | jz pdk4 | ||
| 816 | or bh,NumState | ||
| 817 | pdk4: mov cl,dl | ||
| 818 | and cl,NumState | ||
| 819 | xor bh,cl | ||
| 820 | jz pdk5 | ||
| 821 | pdk41: mov al,ch ; use char2 if shifted or in numlock | ||
| 822 | pdk5: or al,al | ||
| 823 | jnz pdk7 | ||
| 824 | pdk6: cmp ah,-1 | ||
| 825 | jz pdk8 ; Ignore CTRL with keypad 2, etc. | ||
| 826 | cmp ah,76 | ||
| 827 | jz pdk8 | ||
| 828 | pdk7: jmp PutKRet | ||
| 829 | pdk8: jmp KeyRet | ||
| 830 | |||
| 831 | |||
| 832 | ;---------------------------------------------------- | ||
| 833 | ; | ||
| 834 | ; Function Key | ||
| 835 | ; | ||
| 836 | FuncKey: | ||
| 837 | call NoBreak | ||
| 838 | test dl,AltShift+CtrlShift+LeftShift+RightShift | ||
| 839 | jz fk1 ; Normal function key | ||
| 840 | add ah,84-59 | ||
| 841 | test dl,AltShift+CtrlShift | ||
| 842 | jz fk1 ; Shifted function key | ||
| 843 | add ah,10 | ||
| 844 | test dl,AltShift | ||
| 845 | jz fk1 ; Just CTRL function key | ||
| 846 | add ah,10 | ||
| 847 | test dl,CtrlShift | ||
| 848 | jz fk1 ; Just ALT function key | ||
| 849 | mov bx,offset KeyMapTable | ||
| 850 | cmp ah,104 ; CTRL ALT f1 to use normal keyboard | ||
| 851 | jz fk01 | ||
| 852 | cmp ah,105 ; CTRL ALT f2 for foreign keyboard | ||
| 853 | jnz fk1 ; if not F1 or F2 then treat as ALT | ||
| 854 | mov bx,offset ForeignTable | ||
| 855 | fk01: | ||
| 856 | cli ; Change translation table used | ||
| 857 | ; mov word ptr [KeyVector],bx | ||
| 858 | ; mov word ptr [KeyVector+2],cs | ||
| 859 | jmp KeyRet | ||
| 860 | |||
| 861 | fk1: jmp MakeAlt | ||
| 862 | |||
| 863 | |||
| 864 | ;-------------------------------------------------------------------- | ||
| 865 | ; | ||
| 866 | ; Print Screen Key | ||
| 867 | ; | ||
| 868 | PrintScreen: | ||
| 869 | call NoAlt | ||
| 870 | test dl,CtrlShift | ||
| 871 | jz ps1 | ||
| 872 | mov ah,ch | ||
| 873 | jmp fk1 | ||
| 874 | ps1: test dl,LeftShift+RightShift | ||
| 875 | jz pdk7 | ||
| 876 | call VideoOn ;CTRL PrtSc - enable video and do Print Screen | ||
| 877 | ;*a int 5 | ||
| 878 | jmp RestoreRegs | ||
| 879 | |||
| 880 | |||
| 881 | ;-------------------------------------------------------------------- | ||
| 882 | ; | ||
| 883 | ; Space Key | ||
| 884 | ; | ||
| 885 | SpaceKey: | ||
| 886 | call NoBreak | ||
| 887 | test dl, CtrlShift | ||
| 888 | jz sp1 | ||
| 889 | test dl, AltShift | ||
| 890 | jz sp1 | ||
| 891 | jmp KeyRet ; Don't return anything on CTRL-ALT space | ||
| 892 | sp1: | ||
| 893 | jmp PutKRet | ||
| 894 | |||
| 895 | |||
| 896 | ;-------------------------------------------------------------------- | ||
| 897 | ; | ||
| 898 | ; An accent key | ||
| 899 | ; | ||
| 900 | ; Each accent key is assumed to be accent both non-shifted | ||
| 901 | ; and shifted, and the accent number for the shifted should | ||
| 902 | ; be the next one up from the unshifted accent number. | ||
| 903 | ; | ||
| 904 | ;AccKey: | ||
| 905 | ; call NoBreak | ||
| 906 | ; cbw ;convert accent number to an index | ||
| 907 | ; mov bx, ax | ||
| 908 | ; dec bx | ||
| 909 | ; shl bx,1 | ||
| 910 | ; shl bx,1 ;index to table of AccChStruc's | ||
| 911 | ; test dl, altshift | ||
| 912 | ; jz acc2 ;ALT not down | ||
| 913 | ; mov ax, [AccChTbl+bx].alt | ||
| 914 | ; jmp short acc5 | ||
| 915 | ;acc2: | ||
| 916 | ; test dl, ctrlshift | ||
| 917 | ; jz acc3 ;just a normal or shifted keypress | ||
| 918 | ; mov ax, [AccChTbl+bx].ctrl | ||
| 919 | ; jmp short acc5 | ||
| 920 | ;acc3: | ||
| 921 | ; test dl, leftshift+rightshift | ||
| 922 | ; jz acc4 ; not shifted (caps lock not used) | ||
| 923 | ; mov Accent,ch ; Get shifted accent number | ||
| 924 | ; mov ax, [AccChTbl+bx].shift | ||
| 925 | ; mov AccentKey, ax ; Save key and scn code next key int | ||
| 926 | ; jmp KeyRet | ||
| 927 | ;acc4: | ||
| 928 | ; mov Accent, al | ||
| 929 | ; mov ax, [AccChTbl+bx].normal | ||
| 930 | ; mov AccentKey, ax | ||
| 931 | ; jmp KeyRet | ||
| 932 | ;acc5: | ||
| 933 | ; jmp PutKRet | ||
| 934 | ; | ||
| 935 | |||
| 936 | |||
| 937 | ;-------------------------------------------------------------------- | ||
| 938 | ; | ||
| 939 | ; System Request Key | ||
| 940 | ; | ||
| 941 | SysReq: | ||
| 942 | test ah, 80h | ||
| 943 | jnz sys2 ;this is break code | ||
| 944 | test BreakState, SysShift | ||
| 945 | jz sys1 | ||
| 946 | jmp KeyRet ;Ignore if SysReq already down | ||
| 947 | |||
| 948 | sys1: | ||
| 949 | or BreakState, SysShift ;set held down flag | ||
| 950 | mov ax, 08500h | ||
| 951 | jmp short sys3 | ||
| 952 | sys2: | ||
| 953 | and BreakState, Not SysShift ;turn off held down flag | ||
| 954 | mov ax, 08501h | ||
| 955 | sys3: | ||
| 956 | push ax ; Save SysReq action number | ||
| 957 | mov al,20h ; EOI to control port | ||
| 958 | ; out 20h,al | ||
| 959 | call EnableKB | ||
| 960 | pop ax | ||
| 961 | ; int 15h ; Indicate SysReq to BIOS | ||
| 962 | jmp RestoreRegs | ||
| 963 | |||
| 964 | |||
| 965 | |||
| 966 | |||
| 967 | ;*** Finish up processing of interrupt | ||
| 968 | ; | ||
| 969 | |||
| 970 | ;* Make this an ALT seq by removing chr code (ret scan code, 0) | ||
| 971 | MakeAlt:mov al,0 | ||
| 972 | |||
| 973 | ;* Put Key in buffer and return | ||
| 974 | PutKRet: | ||
| 975 | ; cmp Accent, 0 ; check for accented char | ||
| 976 | ; je puk3 ;no accent pressed, just put out key | ||
| 977 | ; mov bl, Accent | ||
| 978 | ; dec bl ;make accent no an index | ||
| 979 | ; xor bh,bh | ||
| 980 | ; mov Accent, bh ;Accent only this character | ||
| 981 | ; shl bx,1 ;index into word table | ||
| 982 | ; mov si, AccentChTbl[bx] ;Get pointer to string for this accent | ||
| 983 | ; dec si ;Negate effect of initial inc in loop | ||
| 984 | ;puk1: | ||
| 985 | ; inc si | ||
| 986 | ; cmp al,cs:[si] | ||
| 987 | ; jz puk2 ;This is an accentable char - so remap | ||
| 988 | ; cmp byte ptr cs:[si], 0 | ||
| 989 | ; jnz puk1 ;not done yet | ||
| 990 | ; | ||
| 991 | ;;* The character is not in this list, so do a beep and put | ||
| 992 | ;; out booth accent char and this char | ||
| 993 | ; call ErrBeep | ||
| 994 | ; mov bx,ax | ||
| 995 | ; mov ax,AccentKey ;Put out accent | ||
| 996 | ; call PutKey | ||
| 997 | ; mov ax,bx | ||
| 998 | ; cmp al, ' ' | ||
| 999 | ; je puk4 ;Char is space, just beep and put out accent. | ||
| 1000 | ; jmp short puk3 ;Put out the character | ||
| 1001 | ; | ||
| 1002 | ;puk2: | ||
| 1003 | ; xor ah, ah ;Zero scan code for accented chrs | ||
| 1004 | ; cmp al, 0 ;for accented ALT chr put out 0, don't beep | ||
| 1005 | ; je puk3 | ||
| 1006 | ; sub si, AccentChTbl[bx] ; Make index to map table | ||
| 1007 | ; add si, AccentMpTbl[bx] | ||
| 1008 | ; mov al, cs:[si] ; Get remapped char | ||
| 1009 | puk3: | ||
| 1010 | call PutKey | ||
| 1011 | puk4: | ||
| 1012 | cmp [PCType],PC_AT | ||
| 1013 | jnz KeyRet ; just return for non-AT | ||
| 1014 | cli | ||
| 1015 | mov al,20h ; EOI to control port | ||
| 1016 | ; out 20h,al | ||
| 1017 | call EnableKB | ||
| 1018 | ; mov ax, 09102h ; Send a post code | ||
| 1019 | ; int 15h | ||
| 1020 | jmp RestoreRegs | ||
| 1021 | |||
| 1022 | |||
| 1023 | |||
| 1024 | ;* Common validity check routines (Check for ALT, ignore break codes) | ||
| 1025 | ; | ||
| 1026 | |||
| 1027 | NoAlt: test dl,AltShift ; Don't allow ALT with this key | ||
| 1028 | jnz IgB1 | ||
| 1029 | NoBreak: ; Ignore break code for this key | ||
| 1030 | mov bl,0 | ||
| 1031 | NoBreak2: | ||
| 1032 | test ah,80h | ||
| 1033 | jnz IgB1 | ||
| 1034 | test [BreakState],HoldState ; in hold state? | ||
| 1035 | jz IgB0 ; no... | ||
| 1036 | and [BreakState],(255-HoldState) | ||
| 1037 | jmp short IgB1 | ||
| 1038 | IgB0: mov [AltKey],bl | ||
| 1039 | ret | ||
| 1040 | IgB1: pop ax ; pop off return address | ||
| 1041 | jmp short KeyRet | ||
| 1042 | |||
| 1043 | |||
| 1044 | ;* buffer is full, beep the speaker and return from interrupt | ||
| 1045 | BufferFull: | ||
| 1046 | cli | ||
| 1047 | mov al,20h | ||
| 1048 | ; out 20h,al | ||
| 1049 | call ErrBeep | ||
| 1050 | jmp short KeyRet1 | ||
| 1051 | |||
| 1052 | |||
| 1053 | ;* Normal return from interrupt, handle EOI and enable KB | ||
| 1054 | KeyRet: | ||
| 1055 | cli | ||
| 1056 | mov al,20h | ||
| 1057 | ; out 20h,al | ||
| 1058 | KeyRet1: | ||
| 1059 | call EnableKB | ||
| 1060 | RestoreRegs: | ||
| 1061 | cli | ||
| 1062 | pop es | ||
| 1063 | pop ds | ||
| 1064 | pop di | ||
| 1065 | pop si | ||
| 1066 | pop dx | ||
| 1067 | pop cx | ||
| 1068 | pop bx | ||
| 1069 | pop ax | ||
| 1070 | ppp proc near | ||
| 1071 | ret | ||
| 1072 | ppp endp | ||
| 1073 | ; iret | ||
| 1074 | |||
| 1075 | |||
| 1076 | SUBTTL Subroutines | ||
| 1077 | |||
| 1078 | |||
| 1079 | |||
| 1080 | |||
| 1081 | ;*** VideoOn - enable keyboard and video | ||
| 1082 | ; | ||
| 1083 | ; ENTRY: Nothing | ||
| 1084 | ; | ||
| 1085 | ; EXIT: (dx), (al) destroyed. | ||
| 1086 | ; | ||
| 1087 | VideoOn proc near | ||
| 1088 | mov al,20h ; EOI to control port | ||
| 1089 | ; out 20h,al | ||
| 1090 | call EnableKB ; Enable AT keyboard | ||
| 1091 | cmp [VidMode],7 | ||
| 1092 | jz vdo1 ; Do nothing for monochrome monitor | ||
| 1093 | mov al,[VidReg] | ||
| 1094 | mov dx,3d8h | ||
| 1095 | out dx,al ; Enable video controller | ||
| 1096 | vdo1: ret | ||
| 1097 | VideoOn endp | ||
| 1098 | |||
| 1099 | |||
| 1100 | |||
| 1101 | |||
| 1102 | ;*** EnableKB - Enable the keyboard interface on an AT, no effect on PC/XT. | ||
| 1103 | ; | ||
| 1104 | ; ENTRY: Nothing | ||
| 1105 | ; | ||
| 1106 | ; EXIT: (al) destroyed | ||
| 1107 | ; | ||
| 1108 | ; EFFECTS: Enables the Keyboard interface. | ||
| 1109 | ; | ||
| 1110 | EnableKB proc near | ||
| 1111 | cmp [PCType], PC_AT | ||
| 1112 | jne ena1 ;for non-AT simply ignore | ||
| 1113 | pushf ;* save interrupt status | ||
| 1114 | cli | ||
| 1115 | call WaitStatus | ||
| 1116 | mov al,0AEh ;output enable keyboard command | ||
| 1117 | out KbStatus,al | ||
| 1118 | popf ;* restore original interrupt status | ||
| 1119 | ;* sti | ||
| 1120 | ena1: | ||
| 1121 | ret | ||
| 1122 | EnableKB endp | ||
| 1123 | |||
| 1124 | |||
| 1125 | |||
| 1126 | |||
| 1127 | ;*** DisableKB - Disable the keyboard interface on an AT, no effect on PC/XT | ||
| 1128 | ; | ||
| 1129 | ; ENTRY: Nothing | ||
| 1130 | ; | ||
| 1131 | ; EXIT: (al) destroyed | ||
| 1132 | ; | ||
| 1133 | ; EFFECTS: Disables the Keyboard interface. | ||
| 1134 | ; | ||
| 1135 | DisableKB proc near | ||
| 1136 | cmp [PCType], PC_AT | ||
| 1137 | jne dis1 ; Ignore if not an AT | ||
| 1138 | pushf ;* save interrupt status | ||
| 1139 | cli | ||
| 1140 | call WaitStatus | ||
| 1141 | mov al,0ADh ;output disable command | ||
| 1142 | out KBStatus, al | ||
| 1143 | popf ;* restore original interrupt status | ||
| 1144 | ;* sti | ||
| 1145 | dis1: | ||
| 1146 | ret | ||
| 1147 | DisableKB endp | ||
| 1148 | |||
| 1149 | |||
| 1150 | |||
| 1151 | |||
| 1152 | ;*** ErrBeep - beep the speaker | ||
| 1153 | ; | ||
| 1154 | ; ENTRY: Nothing | ||
| 1155 | ; | ||
| 1156 | ; EXIT: Nothing | ||
| 1157 | ; | ||
| 1158 | ; USES: (ax) - to access I/O port | ||
| 1159 | ; (bx) - length of beep in cycles | ||
| 1160 | ; (cx) - counter for cycle length | ||
| 1161 | ; | ||
| 1162 | ; EFFECTS: Speaker is beeped | ||
| 1163 | ; | ||
| 1164 | ; WARNING: Uses in/out to keyboard port to beep speaker directly. | ||
| 1165 | ; | ||
| 1166 | ErrBeep proc near | ||
| 1167 | push ax | ||
| 1168 | push bx | ||
| 1169 | push cx | ||
| 1170 | mov bx,BeepDur ; count of speaker cycles | ||
| 1171 | in al,KbCtl | ||
| 1172 | push ax | ||
| 1173 | and al,0fch ; turn off bits 0 and 1 (speaker off) | ||
| 1174 | bee1: xor al,2 ; toggle speaker bit | ||
| 1175 | out KbCtl,al | ||
| 1176 | mov cx,BeepFreq | ||
| 1177 | bee2: loop bee2 ; wait for half cycle | ||
| 1178 | dec bx | ||
| 1179 | jnz bee1 ; keep cycling speaker | ||
| 1180 | pop ax ; restore speaker/keyboard port value | ||
| 1181 | out KbCtl,al | ||
| 1182 | pop cx | ||
| 1183 | pop bx | ||
| 1184 | pop ax | ||
| 1185 | ret | ||
| 1186 | ErrBeep endp | ||
| 1187 | |||
| 1188 | |||
| 1189 | |||
| 1190 | |||
| 1191 | ;*** PutKey - put key in the buffer | ||
| 1192 | ; | ||
| 1193 | ; ENTRY: (ax) = key code and scn code to go in buffer | ||
| 1194 | ; | ||
| 1195 | ; EXIT: (si), (di) destroyed. | ||
| 1196 | ; ints disabled. | ||
| 1197 | ; | ||
| 1198 | ; EFFECTS: KbTail updated | ||
| 1199 | ; (ax) put in buffer at end. | ||
| 1200 | ; On AT - do post call. | ||
| 1201 | ; | ||
| 1202 | ; If it isn't possible to put key in buffer (full) then beep | ||
| 1203 | ; and ignore. | ||
| 1204 | ; If (ax) = -1 then the key is not put in buffer. | ||
| 1205 | ; | ||
| 1206 | PutKey proc near | ||
| 1207 | cmp ax, -1 ; Code to ignore a key | ||
| 1208 | jz put2 | ||
| 1209 | cli ; Make sure only ones using buffer now | ||
| 1210 | mov si,[KbTail] | ||
| 1211 | mov di,si ; Get old buffer end and save it | ||
| 1212 | inc si ; Advance pointer | ||
| 1213 | inc si | ||
| 1214 | cmp si,[KbEnd] | ||
| 1215 | jb put01 | ||
| 1216 | mov si,[KbStart] ; Wrap to beginning if at end | ||
| 1217 | put01: | ||
| 1218 | cmp si,[KbHead] | ||
| 1219 | jnz put1 ; Buffer not Full | ||
| 1220 | pop ax ; Drop return address | ||
| 1221 | jmp BufferFull ; Go beep and return from interrupt | ||
| 1222 | |||
| 1223 | put1: | ||
| 1224 | mov [di],ax ; Put key in buffer at end | ||
| 1225 | mov [KbTail],si | ||
| 1226 | put2: | ||
| 1227 | ret | ||
| 1228 | PutKey endp | ||
| 1229 | |||
| 1230 | |||
| 1231 | |||
| 1232 | |||
| 1233 | ;*** GetSCode - read the scan code from the keyboard | ||
| 1234 | ; | ||
| 1235 | ; ENTRY: nothing | ||
| 1236 | ; | ||
| 1237 | ; EXIT: (al) = key scan code from keyboard | ||
| 1238 | ; (ah) destroyed | ||
| 1239 | ; | ||
| 1240 | ; USES: PCType - to use PC/AT sequence, for AT - handles LEDs | ||
| 1241 | ; | ||
| 1242 | GetSCode proc near | ||
| 1243 | cmp [PCType], PC_AT | ||
| 1244 | je gsc1 ;handle AT differently | ||
| 1245 | in al,KbData ;get key code | ||
| 1246 | xchg bx,ax ;save scan code | ||
| 1247 | in al,KbCtl ;acknowledge to keyboard | ||
| 1248 | mov ah,al | ||
| 1249 | or al,80h | ||
| 1250 | out KbCtl,al | ||
| 1251 | xchg ah,al | ||
| 1252 | out KbCtl,al | ||
| 1253 | xchg ax,bx ;(al) = scan code | ||
| 1254 | ret | ||
| 1255 | |||
| 1256 | gsc1: ;have to do handshake | ||
| 1257 | call DisableKB | ||
| 1258 | pushf ;* save interrupt status | ||
| 1259 | cli | ||
| 1260 | call WaitStatus | ||
| 1261 | in al,KbData ;read in character | ||
| 1262 | popf ;* restore original interrupt status | ||
| 1263 | ;* sti | ||
| 1264 | |||
| 1265 | ; check for and flag control bytes from keyboard | ||
| 1266 | cmp al,ATResend | ||
| 1267 | jne gsc2 ;it isn't a resend | ||
| 1268 | cli | ||
| 1269 | or [ATKbFlags], KbResend | ||
| 1270 | pop bx ;throw away return address | ||
| 1271 | jmp KeyRet ;and don't do anything more with key | ||
| 1272 | |||
| 1273 | gsc2: | ||
| 1274 | cmp al,ATAck | ||
| 1275 | jne gsc3 ;it isn't an ack | ||
| 1276 | cli | ||
| 1277 | or [ATKbFlags], KBAck | ||
| 1278 | pop bx ;throw away return address | ||
| 1279 | jmp KeyRet ;and don't do anything more with key | ||
| 1280 | |||
| 1281 | gsc3: | ||
| 1282 | call UpdateLeds ;update AT's leds | ||
| 1283 | ret | ||
| 1284 | GetSCode endp | ||
| 1285 | |||
| 1286 | |||
| 1287 | |||
| 1288 | ;*** Don't need to keep code after here when not running on an AT | ||
| 1289 | xt_endcode: | ||
| 1290 | |||
| 1291 | |||
| 1292 | |||
| 1293 | ;*** UpdateLeds - update the leds on the AT keyboard | ||
| 1294 | ; | ||
| 1295 | ; ENTRY: Nothing | ||
| 1296 | ; | ||
| 1297 | ; EXIT: All regs preserved | ||
| 1298 | ; | ||
| 1299 | ; EFFECTS: Sets the keyboard LEDs according to the status byte. | ||
| 1300 | ; | ||
| 1301 | ; WARNING: Assumes it is operating on an AT, must not be called for a PC. | ||
| 1302 | ; | ||
| 1303 | UpdateLeds proc near | ||
| 1304 | pushf ;* save interrupt status | ||
| 1305 | push ax | ||
| 1306 | cli | ||
| 1307 | mov ah, KeyState ; get the toggle key states | ||
| 1308 | and ah, CapsState + NumState + ScrollState | ||
| 1309 | rol ah, 1 | ||
| 1310 | rol ah, 1 | ||
| 1311 | rol ah, 1 | ||
| 1312 | rol ah, 1 ; in format for ATKbFlags | ||
| 1313 | mov al, ATKbFlags | ||
| 1314 | and al, 07h | ||
| 1315 | cmp ah, al | ||
| 1316 | jz Updn1 ; No change in leds, so don't update | ||
| 1317 | test ATKbFlags, KBSndLed | ||
| 1318 | jnz Updn1 ; Already updating, so don't update | ||
| 1319 | or ATKbFlags, KBSndLed | ||
| 1320 | mov al, 20h | ||
| 1321 | ; out 20h, al ; send EOI | ||
| 1322 | mov al, 0EDh ; Set indicators command | ||
| 1323 | call SendByte | ||
| 1324 | test ATKbFlags, KBErr | ||
| 1325 | jnz Updn2 | ||
| 1326 | mov al, ah ; Send indicator values | ||
| 1327 | call SendByte | ||
| 1328 | test ATKbFlags, KBErr | ||
| 1329 | jnz Updn2 | ||
| 1330 | and ATKbFlags, 0F8h | ||
| 1331 | or ATKbFlags, ah ; Record indicators | ||
| 1332 | Updn2: | ||
| 1333 | and ATKbFlags, Not (KBSndLed + KBErr) | ||
| 1334 | Updn1: | ||
| 1335 | pop ax | ||
| 1336 | popf ;* restore original interrupt status | ||
| 1337 | ;* sti | ||
| 1338 | ret | ||
| 1339 | UpdateLeds endp | ||
| 1340 | |||
| 1341 | |||
| 1342 | |||
| 1343 | |||
| 1344 | ;*** SendByte - send a byte to the keyboard | ||
| 1345 | ; | ||
| 1346 | ; ENTRY: (al) - command/data to send | ||
| 1347 | ; | ||
| 1348 | ; EXIT: BreakState flags set according to success of operation. | ||
| 1349 | ; Ints disabled on completion. | ||
| 1350 | ; | ||
| 1351 | ; USES: (al) - byte to send. | ||
| 1352 | ; (ah) - count of retries. | ||
| 1353 | ; (cx) - time out counter on wait for response. | ||
| 1354 | ; | ||
| 1355 | ; Send the byte in al to the AT keyboard controller, and | ||
| 1356 | ; do handshaking to make sure they get there OK. | ||
| 1357 | ; Must not be called for the PC. | ||
| 1358 | ; | ||
| 1359 | SendByte proc near | ||
| 1360 | push ax | ||
| 1361 | push cx | ||
| 1362 | mov ah, 03 ; Set up count of retries | ||
| 1363 | Sen1: | ||
| 1364 | pushf ;* save interrupt status | ||
| 1365 | cli | ||
| 1366 | and ATKbFlags, Not (KBResend + KBAck + KBErr) | ||
| 1367 | push ax ; save byte to send | ||
| 1368 | call WaitStatus ; Wait for keyboard ready | ||
| 1369 | pop ax | ||
| 1370 | out KbData, al ; Send byte to keyboard | ||
| 1371 | popf ;* restore original interrupt status | ||
| 1372 | ;* sti | ||
| 1373 | mov cx,2000h ; Time out length, Approximate value for AT ROM | ||
| 1374 | Sen2: ; Wait for ACK | ||
| 1375 | call handler ;*a (look for key since no interrupts) | ||
| 1376 | test ATKbFlags, KBResend + KBAck | ||
| 1377 | jnz Sen4 | ||
| 1378 | loop Sen2 | ||
| 1379 | Sen3: ; Timed out - try to resend | ||
| 1380 | dec ah | ||
| 1381 | jnz Sen1 | ||
| 1382 | or ATKbFlags, KBErr | ||
| 1383 | jmp Sen5 | ||
| 1384 | Sen4: | ||
| 1385 | call handler ;*a (look for key since no interrupts) | ||
| 1386 | test ATKbFlags, KBResend | ||
| 1387 | jnz Sen3 | ||
| 1388 | Sen5: | ||
| 1389 | cli | ||
| 1390 | pop cx | ||
| 1391 | pop ax | ||
| 1392 | ret | ||
| 1393 | SendByte endp | ||
| 1394 | |||
| 1395 | |||
| 1396 | |||
| 1397 | |||
| 1398 | ;*** WaitStatus - wait for status to indicate ready for new command | ||
| 1399 | ; | ||
| 1400 | ; ENTRY: Nothing | ||
| 1401 | ; | ||
| 1402 | ; EXIT: (AL) Destroyed. | ||
| 1403 | ; | ||
| 1404 | WaitStatus proc near | ||
| 1405 | push cx | ||
| 1406 | xor cx,cx | ||
| 1407 | wai1: ;wait for empty buffer | ||
| 1408 | in al,KbStatus | ||
| 1409 | test al,BufFull | ||
| 1410 | loopnz wai1 | ||
| 1411 | pop cx | ||
| 1412 | ret | ||
| 1413 | WaitStatus endp | ||
| 1414 | |||
| 1415 | SUBTTL Initialization | ||
| 1416 | |||
| 1417 | |||
| 1418 | |||
| 1419 | ;* Initialization, called when run by DOS, doesn't stay resident. | ||
| 1420 | ; | ||
| 1421 | init_bios: | ||
| 1422 | |||
| 1423 | mov al,0ffh ; all OFF | ||
| 1424 | out MASTER_IMR,al | ||
| 1425 | |||
| 1426 | push ds | ||
| 1427 | push cs | ||
| 1428 | pop ds ; establish segment, since offsets are from cs | ||
| 1429 | mov dx,offset Kbint | ||
| 1430 | mov ax,2509h | ||
| 1431 | int 21h ;Set interrupt 9 (keyboard) vector | ||
| 1432 | |||
| 1433 | mov ax, romdata | ||
| 1434 | mov ds, ax | ||
| 1435 | init1: cmp [KbStart],0 | ||
| 1436 | jnz init2 ;New PC/AT - KbStart already initialized | ||
| 1437 | pushf ;* save interrupt status | ||
| 1438 | cli ;For old PC - initialize pointers to KbBuffer | ||
| 1439 | mov ax,offset KbBuffer | ||
| 1440 | mov [KbStart],ax | ||
| 1441 | mov [KbHead],ax | ||
| 1442 | mov [KbTail],ax | ||
| 1443 | mov [KbEnd],offset KbBufferEnd | ||
| 1444 | popf ;* restore original interrupt status | ||
| 1445 | ;* sti | ||
| 1446 | init2: ; Start up in Foreign keyboard mode | ||
| 1447 | ; mov word ptr [KeyVector],offset ForeignTable | ||
| 1448 | ; mov word ptr [KeyVector+2],cs | ||
| 1449 | |||
| 1450 | ; mov [accent],0 ; No previous accent key pressed | ||
| 1451 | |||
| 1452 | ; Get PC type information and save in PCType flag | ||
| 1453 | ; assume ds:rom | ||
| 1454 | |||
| 1455 | ; mov ax, rom | ||
| 1456 | ; mov ds, ax | ||
| 1457 | ; mov al, [systid] | ||
| 1458 | ; mov [PCType], al | ||
| 1459 | |||
| 1460 | assume ds:romdata | ||
| 1461 | pop ds | ||
| 1462 | |||
| 1463 | ; mov dx,offset xt_endcode + 100h | ||
| 1464 | ; cmp [PCType], PC_AT | ||
| 1465 | ; jnz init6 ; Drop AT specific code | ||
| 1466 | |||
| 1467 | ;* Initialization specific to AT | ||
| 1468 | ; Set up speaker counts, exchange keys 41, 43 | ||
| 1469 | ; And keep AT specific code when terminate | ||
| 1470 | ; mov [BeepFreq], ATBeepFreq | ||
| 1471 | ; mov [BeepDur], ATBeepDur | ||
| 1472 | |||
| 1473 | ; Reverse keys 41 and 43 for foreign keyboards | ||
| 1474 | ; mov ax, [ForeignTable + (41 * 4)] ; exchange char codes | ||
| 1475 | ; xchg ax, [ForeignTable + (43 * 4)] | ||
| 1476 | ; mov [ForeignTable + (41 * 4)], ax | ||
| 1477 | ; mov ax, [ForeignTable + (41 * 4) + 2] ;exchange function codes also | ||
| 1478 | ; xchg ax, [ForeignTable + (43 * 4) + 2] | ||
| 1479 | ; mov [ForeignTable + (41 * 4) + 2], ax | ||
| 1480 | ; Also handle for Ctrl Alt table | ||
| 1481 | ; mov si, offset AltChrs - 1 | ||
| 1482 | ;init3: ;search AltChrs table | ||
| 1483 | ; inc si | ||
| 1484 | ; cmp si, offset AltChrsEnd | ||
| 1485 | ; jae init5 ;Done scaning - go terminate | ||
| 1486 | ; cmp byte ptr cs:[si], 43 | ||
| 1487 | ; jnz init4 | ||
| 1488 | ; mov byte ptr cs:[si], 41 ; found key 43 - replace with 41 | ||
| 1489 | ; jmp init3 | ||
| 1490 | ;init4: | ||
| 1491 | ; cmp byte ptr cs:[si], 41 | ||
| 1492 | ; jnz init3 | ||
| 1493 | ; mov byte ptr cs:[si], 43 ; found key 41 - replace with 43 | ||
| 1494 | ; jmp init3 | ||
| 1495 | ; | ||
| 1496 | ;init5: | ||
| 1497 | ; mov dx,offset init_bios + 100h ; Keep AT specific code | ||
| 1498 | init6: | ||
| 1499 | ; Terminate and stay resident, don't keep init code | ||
| 1500 | ; push ds ; adjust cs to psp | ||
| 1501 | ; mov bx, offset init7 + 100h ; by doing a far return to init7 | ||
| 1502 | ; push bx | ||
| 1503 | ;xxxx proc far | ||
| 1504 | ; ret | ||
| 1505 | ;xxxx endp | ||
| 1506 | ;init7: | ||
| 1507 | ; int 27h | ||
| 1508 | |||
| 1509 | mov ah, 14 | ||
| 1510 | mov al, 'i' | ||
| 1511 | int 10h | ||
| 1512 | ini1: | ||
| 1513 | |||
| 1514 | ;mov ah, 14 | ||
| 1515 | ;mov al, 'h' | ||
| 1516 | ;int 10h | ||
| 1517 | |||
| 1518 | call handler | ||
| 1519 | ; call getc | ||
| 1520 | jz ini1 | ||
| 1521 | mov ah, 14 | ||
| 1522 | int 10h | ||
| 1523 | jmp ini1 | ||
| 1524 | |||
| 1525 | DCODE ends | ||
| 1526 | |||
| 1527 | ;*** getc - read character out of keyboard buffer | ||
| 1528 | ; | ||
| 1529 | ; This routine gets characters from the buffer | ||
| 1530 | ; in the ROM data area. | ||
| 1531 | ; | ||
| 1532 | ; ENTRY | ||
| 1533 | ; | ||
| 1534 | ; EXIT AL - character | ||
| 1535 | ; AH - scan code | ||
| 1536 | ; 'Z' = 0 | ||
| 1537 | ; | ||
| 1538 | ; or 'Z' = 1 if no code available | ||
| 1539 | ; | ||
| 1540 | ; USES flags | ||
| 1541 | ; | ||
| 1542 | |||
| 1543 | DCODE segment | ||
| 1544 | |||
| 1545 | assume cs:DCODE, ds:nothing, es:nothing, ss:nothing | ||
| 1546 | |||
| 1547 | public kgetc | ||
| 1548 | kgetc proc far | ||
| 1549 | |||
| 1550 | push bx | ||
| 1551 | push cx | ||
| 1552 | push dx | ||
| 1553 | push si | ||
| 1554 | push di | ||
| 1555 | |||
| 1556 | mov bx, 202h | ||
| 1557 | mov cx, 303h | ||
| 1558 | mov dx, 404h | ||
| 1559 | mov si, 505h | ||
| 1560 | mov di, 606h | ||
| 1561 | |||
| 1562 | call handler ; pull data into kbd buffer | ||
| 1563 | |||
| 1564 | mov bx, 2020h | ||
| 1565 | mov cx, 3030h | ||
| 1566 | mov dx, 4040h | ||
| 1567 | mov si, 5050h | ||
| 1568 | mov di, 6060h | ||
| 1569 | |||
| 1570 | push ds ; save caller's regs | ||
| 1571 | push bx | ||
| 1572 | |||
| 1573 | mov bx, romdata | ||
| 1574 | mov ds, bx ; DS -> ROM data area | ||
| 1575 | |||
| 1576 | cli | ||
| 1577 | mov bx, ds:[KbHead] ; bx = start of buffer | ||
| 1578 | cmp bx, ds:[KbTail] ; is buffer empty | ||
| 1579 | ;* sti | ||
| 1580 | jz ge1 | ||
| 1581 | |||
| 1582 | cli | ||
| 1583 | mov ax, [bx] ; AX = character and scan code | ||
| 1584 | add bx, 2 ; step buffer pointer | ||
| 1585 | cmp bx, ds:[KbEnd] ; is it at end of buffer | ||
| 1586 | jne ge2 | ||
| 1587 | mov bx, ds:[KbStart] ; move it back to start | ||
| 1588 | ge2: | ||
| 1589 | mov ds:[KbHead], bx ; store new start pointer | ||
| 1590 | ;* sti | ||
| 1591 | and bx, 0ffffh ; just to clear zero flag | ||
| 1592 | ge1: | ||
| 1593 | pop bx | ||
| 1594 | pop ds | ||
| 1595 | |||
| 1596 | pop di | ||
| 1597 | pop si | ||
| 1598 | pop dx | ||
| 1599 | pop cx | ||
| 1600 | pop bx | ||
| 1601 | |||
| 1602 | ret | ||
| 1603 | |||
| 1604 | kgetc endp | ||
| 1605 | |||
| 1606 | DCODE ends | ||
| 1607 | end | ||
| 1608 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/KBD.INC b/v4.0/src/MEMM/MEMM/KBD.INC new file mode 100644 index 0000000..ce3ca1a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/KBD.INC | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: KBD.INC - KBD.ASM Structures and Equates | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ; Functional Description: | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ifndef INC_LIST | ||
| 33 | .xlist | ||
| 34 | endif | ||
| 35 | |||
| 36 | ; SCCSID = @(#)keybxx.inc 1.1 85/10/09 | ||
| 37 | ;------------------------------------------------------ | ||
| 38 | ; | ||
| 39 | ; Keybxx.inc - Define struct and equates for KeybXX and Keyb??.ASM . | ||
| 40 | ; | ||
| 41 | ; Keyb?? - denotes any of the files keybfr, keybgr, keybit, keybuk, | ||
| 42 | ; keybsp or keybdv (Dvorak keyboard). | ||
| 43 | ; | ||
| 44 | |||
| 45 | |||
| 46 | esc equ 1bh | ||
| 47 | |||
| 48 | |||
| 49 | KbData equ 60h ; I/O Ports for keyboard | ||
| 50 | KbCtl equ 61h | ||
| 51 | KbStatus equ 64h | ||
| 52 | |||
| 53 | PCBeepFreq equ 48h ; Count for Beep frequency | ||
| 54 | PCBeepDur equ 105h ; Number of Beep half cycles | ||
| 55 | ATBeepFreq equ 0CEh ; Use larger values since AT faster | ||
| 56 | ATBeepDur equ 82h | ||
| 57 | |||
| 58 | InsState equ 80h ; Bit values for BreakState and KeyState | ||
| 59 | CapsState equ 40h | ||
| 60 | NumState equ 20h | ||
| 61 | ScrollState equ 10h | ||
| 62 | HoldState equ 08h | ||
| 63 | |||
| 64 | |||
| 65 | AltShift equ 08h ; Bit values for KeyState | ||
| 66 | CtrlShift equ 04h | ||
| 67 | LeftShift equ 02h | ||
| 68 | RightShift equ 01h | ||
| 69 | |||
| 70 | |||
| 71 | BufFull equ 02h ; Bit value for KbStatus port | ||
| 72 | |||
| 73 | |||
| 74 | ATResend equ 0FEh ; AT keyboard commands | ||
| 75 | ATAck equ 0FAh | ||
| 76 | |||
| 77 | |||
| 78 | KBErr equ 080h ; Bit values for ATKbFlags | ||
| 79 | KBSndLed equ 040h | ||
| 80 | KBResend equ 020h | ||
| 81 | KBAck equ 010h | ||
| 82 | SysShift equ 004h ;SysReq key held down | ||
| 83 | |||
| 84 | |||
| 85 | ;*** AccChStruc - Structure for information about accent keys | ||
| 86 | ; | ||
| 87 | ; Contains scan and char codes returned for all shift combinations | ||
| 88 | ; with an accent key. | ||
| 89 | ; | ||
| 90 | ; Note: an accent key is an accent in both normal and shifted mode. | ||
| 91 | ; | ||
| 92 | AccChStruc struc | ||
| 93 | normal dw 0 ;chr & scan code for unshifted accent key | ||
| 94 | shift dw 0 ; " " " for shifted " " | ||
| 95 | ctrl dw -1 | ||
| 96 | alt dw -1 | ||
| 97 | AccChStruc ends | ||
| 98 | |||
| 99 | .list ; end of KBD.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/LOADALL.INC b/v4.0/src/MEMM/MEMM/LOADALL.INC new file mode 100644 index 0000000..bd31ec4 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/LOADALL.INC | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; **** INTEL PROPRIETARY **** | ||
| 7 | ; | ||
| 8 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 9 | ; | ||
| 10 | ; Module: LOADALL - contains structures for 286 and 386 loadall | ||
| 11 | ; | ||
| 12 | ; Version: 0.02 | ||
| 13 | ; | ||
| 14 | ; Date: April 11,1986 | ||
| 15 | ; | ||
| 16 | ; Author: | ||
| 17 | ; | ||
| 18 | ;****************************************************************************** | ||
| 19 | ; | ||
| 20 | ; Change log: | ||
| 21 | ; | ||
| 22 | ; DATE REVISION DESCRIPTION | ||
| 23 | ; -------- -------- ------------------------------------------------------- | ||
| 24 | ; 04/11/86 Original | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ifndef INC_LIST | ||
| 30 | .xlist | ||
| 31 | endif | ||
| 32 | |||
| 33 | LODAL286 equ 050Fh ; instruction as a WORD | ||
| 34 | LODAL386 equ 070Fh ; instruction as a WORD | ||
| 35 | |||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Note that entries are statically initialized to 0000, so limits and | ||
| 39 | ; access rights must be set up at run time. | ||
| 40 | ; | ||
| 41 | ; Structure of a 286 system table/segment descriptor cache: | ||
| 42 | ; | ||
| 43 | DescCache286 struc | ||
| 44 | dc2_BASElo dw 0000 ; low word of base (0..15) | ||
| 45 | dc2_BASEhi db 00 ; high byte of base (16..24) | ||
| 46 | dc2_AR db 00 ; access rights byte | ||
| 47 | dc2_LIMIT dw 0000 ; segment limit | ||
| 48 | DescCache286 ends | ||
| 49 | ; | ||
| 50 | ; Structure of the 286 LOADALL buffer | ||
| 51 | ; | ||
| 52 | LoadAllBuf286 struc | ||
| 53 | |||
| 54 | ll2_None1 db 6 dup (0) ; temp | ||
| 55 | ll2_MSW dw 0000 ; MSW | ||
| 56 | ll2_None2 db 14 dup (0) ; temp | ||
| 57 | ll2_TR dw 0000 ; TR | ||
| 58 | ll2_FLAGS dw 0000 ; FLAGS | ||
| 59 | ll2_IP dw 0000 ; IP | ||
| 60 | ll2_LDT dw 0000 ; LDT | ||
| 61 | ll2_DS dw 0000 ; DS | ||
| 62 | ll2_SS dw 0000 ; SS | ||
| 63 | ll2_CS dw 0000 ; CS | ||
| 64 | ll2_ES dw 0000 ; ES | ||
| 65 | ll2_DI dw 0000 ; DI | ||
| 66 | ll2_SI dw 0000 ; SI | ||
| 67 | ll2_BP dw 0000 ; BP | ||
| 68 | ll2_SP dw 0000 ; SP | ||
| 69 | ll2_BX dw 0000 ; BX | ||
| 70 | ll2_DX dw 0000 ; DX | ||
| 71 | ll2_CX dw 0000 ; CX | ||
| 72 | ll2_AX dw 0000 ; AX | ||
| 73 | |||
| 74 | ; | ||
| 75 | ; System table and segment descriptor caches | ||
| 76 | ; | ||
| 77 | ll2_EScache db size DescCache286 dup (00) | ||
| 78 | ll2_CScache db size DescCache286 dup (00) | ||
| 79 | ll2_SScache db size DescCache286 dup (00) | ||
| 80 | ll2_DScache db size DescCache286 dup (00) | ||
| 81 | ll2_GDTcache db size DescCache286 dup (00) | ||
| 82 | ll2_LDTcache db size DescCache286 dup (00) | ||
| 83 | ll2_IDTcache db size DescCache286 dup (00) | ||
| 84 | ll2_TSScache db size DescCache286 dup (00) | ||
| 85 | |||
| 86 | LoadAllBuf286 ends | ||
| 87 | ; | ||
| 88 | |||
| 89 | ; | ||
| 90 | ;****************************************************************************** | ||
| 91 | ; Define the 386 LOADALL buffer structure - 'nested' structures must be | ||
| 92 | ; used because the complete definition is too complex for the linker. | ||
| 93 | ; Note that entries are statically initialized to 0000, so limits and | ||
| 94 | ; access rights must be set up at run time. | ||
| 95 | ; | ||
| 96 | ; Structure of a 386 system table/segment descriptor cache: | ||
| 97 | ; | ||
| 98 | DescCache386 struc | ||
| 99 | dc3_AR1 db 00 ; base 16..23 (ignored) | ||
| 100 | dc3_AR2 db 00 ; access rights byte | ||
| 101 | dc3_AR3 db 00 ; limit 16..19 (ignored), B/D, G | ||
| 102 | dc3_AR4 db 00 ; base 24..31 (ignored) | ||
| 103 | dc3_BASElo dw 0000 ; low word of base | ||
| 104 | dc3_BASEhi dw 0000 ; high word of base | ||
| 105 | dc3_LIMITlo dw 0000 ; low word of limit | ||
| 106 | dc3_LIMIThi dw 0000 ; high word of limit | ||
| 107 | DescCache386 ends | ||
| 108 | ; | ||
| 109 | ; Structure of the 386 LOADALL buffer | ||
| 110 | ; | ||
| 111 | LoadAllBuf386 struc | ||
| 112 | |||
| 113 | ll3_CR0 dw 0000 ; low word of CR0 | ||
| 114 | ll3_CR0hi dw 0000 ; high word of CR0 | ||
| 115 | ll3_EFLAGS dw 0000 ; low word of EFLAGS | ||
| 116 | ll3_EFLAGShi dw 0000 ; high word of EFLAGS | ||
| 117 | ll3_EIP dw 0000 ; low word of EIP | ||
| 118 | ll3_EIPhi dw 0000 ; high word of EIP | ||
| 119 | ll3_EDI dw 0000 ; low word of EDI | ||
| 120 | ll3_EDIhi dw 0000 ; high word of EDI | ||
| 121 | ll3_ESI dw 0000 ; low word of ESI | ||
| 122 | ll3_ESIhi dw 0000 ; high word of ESI | ||
| 123 | ll3_EBP dw 0000 ; low word of EBP | ||
| 124 | ll3_EBPhi dw 0000 ; high word of EBP | ||
| 125 | ll3_ESP dw 0000 ; low word of ESP | ||
| 126 | ll3_ESPhi dw 0000 ; high word of ESP | ||
| 127 | ll3_EBX dw 0000 ; low word of EBX | ||
| 128 | ll3_EBXhi dw 0000 ; high word of EBX | ||
| 129 | ll3_EDX dw 0000 ; low word of EDX | ||
| 130 | ll3_EDXhi dw 0000 ; high word of EDX | ||
| 131 | ll3_ECX dw 0000 ; low word of ECX | ||
| 132 | ll3_ECXhi dw 0000 ; high word of ECX | ||
| 133 | ll3_EAX dw 0000 ; low word of EAX | ||
| 134 | ll3_EAXhi dw 0000 ; high word of EAX | ||
| 135 | ll3_DR6 dw 0000 ; low word of DR6 | ||
| 136 | ll3_DR6hi dw 0000 ; high word of DR6 | ||
| 137 | ll3_DR7 dw 0000 ; low word of DR7 | ||
| 138 | ll3_DR7hi dw 0000 ; high word of DR7 | ||
| 139 | ll3_TSSR dw 0000 ; TSSR (TSS selector) | ||
| 140 | dw 0000 ; (padding) | ||
| 141 | ll3_LDTR dw 0000 ; LDTR (LDT selector) | ||
| 142 | dw 0000 ; (padding) | ||
| 143 | ll3_GS dw 0000 ; GS | ||
| 144 | dw 0000 ; (padding) | ||
| 145 | ll3_FS dw 0000 ; FS | ||
| 146 | dw 0000 ; (padding) | ||
| 147 | ll3_DS dw 0000 ; DS | ||
| 148 | dw 0000 ; (padding) | ||
| 149 | ll3_SS dw 0000 ; SS | ||
| 150 | dw 0000 ; (padding) | ||
| 151 | ll3_CS dw 0000 ; CS | ||
| 152 | dw 0000 ; (padding) | ||
| 153 | ll3_ES dw 0000 ; ES | ||
| 154 | dw 0000 ; (padding) | ||
| 155 | ; | ||
| 156 | ; System table and segment descriptor caches | ||
| 157 | ; | ||
| 158 | ll3_TSScache db size DescCache386 dup (00) | ||
| 159 | ll3_IDTcache db size DescCache386 dup (00) | ||
| 160 | ll3_GDTcache db size DescCache386 dup (00) | ||
| 161 | ll3_LDTcache db size DescCache386 dup (00) | ||
| 162 | ll3_GScache db size DescCache386 dup (00) | ||
| 163 | ll3_FScache db size DescCache386 dup (00) | ||
| 164 | ll3_DScache db size DescCache386 dup (00) | ||
| 165 | ll3_SScache db size DescCache386 dup (00) | ||
| 166 | ll3_CScache db size DescCache386 dup (00) | ||
| 167 | ll3_EScache db size DescCache386 dup (00) | ||
| 168 | |||
| 169 | ll3_temps db 134h dup (00) ; padding for internal temps | ||
| 170 | |||
| 171 | LoadAllBuf386 ends | ||
| 172 | |||
| 173 | .list ; end of LOADALL.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/MACH_ID.INC b/v4.0/src/MEMM/MEMM/MACH_ID.INC new file mode 100644 index 0000000..ba217cb --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MACH_ID.INC | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: MACH_ID.INC - include for Machine ID types | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: April 9, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 04/09/86 Original | ||
| 24 | ; | ||
| 25 | ;****************************************************************************** | ||
| 26 | ifndef INC_LIST | ||
| 27 | .xlist | ||
| 28 | endif | ||
| 29 | |||
| 30 | ; STANDARD ROM BIOS MACHINE TYPES used in ROM_BIOS_Machine_ID | ||
| 31 | |||
| 32 | RBMI_PC equ 0FFh | ||
| 33 | RBMI_PCXT equ 0FEh | ||
| 34 | RBMI_PCjr equ 0FDh | ||
| 35 | RBMI_PCAT equ 0FCh | ||
| 36 | RBMI_PCConvertible equ 0F9h | ||
| 37 | RBMI_Sys80 equ 0F8h | ||
| 38 | RBMI_CompaqPortable equ 000h | ||
diff --git a/v4.0/src/MEMM/MEMM/MAKEFILE b/v4.0/src/MEMM/MEMM/MAKEFILE new file mode 100644 index 0000000..9f1a77b --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAKEFILE | |||
| @@ -0,0 +1,343 @@ | |||
| 1 | #****************************************************************************** | ||
| 2 | # title MAKEFILE - MEMM build file | ||
| 3 | #****************************************************************************** | ||
| 4 | # | ||
| 5 | # (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | # | ||
| 7 | # Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | # | ||
| 9 | # Module: MAKEFILE | ||
| 10 | # | ||
| 11 | # Version: 0.06 | ||
| 12 | # | ||
| 13 | # Date: May 12, 1986 | ||
| 14 | # | ||
| 15 | # Author: | ||
| 16 | # | ||
| 17 | #****************************************************************************** | ||
| 18 | # | ||
| 19 | # Change log: | ||
| 20 | # | ||
| 21 | # DATE REVISION DESCRIPTION | ||
| 22 | # -------- -------- ------------------------------------------------------- | ||
| 23 | # Original | ||
| 24 | # 05/12/86 B- Cleanup and segment reorganization | ||
| 25 | # 06/03/86 C- Added module for driver i/f | ||
| 26 | # 06/08/86 C- Merge in lastest code from MS | ||
| 27 | # 06/17/86 D- Added debug version. | ||
| 28 | # 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 29 | # 07/01/86 0.03 Added MapDMA module. | ||
| 30 | # 07/11/86 0.05 Moved HIFLAG into global includes. | ||
| 31 | # | ||
| 32 | #****************************************************************************** | ||
| 33 | # | ||
| 34 | # Functional Description: | ||
| 35 | # | ||
| 36 | # This file assembles and links | ||
| 37 | # (1) EMM386.EXE - Production version of EMM386 driver | ||
| 38 | # (2) EMM386.COM - Production version of EMM386 utility | ||
| 39 | # (3) EMM386D.EXE - Debug (Internal) version of EMM386 driver | ||
| 40 | # | ||
| 41 | #****************************************************************************** | ||
| 42 | |||
| 43 | #****************************************************************************** | ||
| 44 | # R U L E S and M A C R O S | ||
| 45 | #****************************************************************************** | ||
| 46 | .SUFFIXES: | ||
| 47 | .SUFFIXES: .c .asm .obj .lst .def .lnk .lrf .exe .com | ||
| 48 | |||
| 49 | |||
| 50 | # Definition for turning OFF high memory allocation | ||
| 51 | # HIFLAG = -DNOHIMEM => turns it off | ||
| 52 | # HIFLAG = => turns on high memory allocation | ||
| 53 | HIFLAG = -DNOHIMEM | ||
| 54 | #HIFLAG = | ||
| 55 | |||
| 56 | # Definitions for assembler | ||
| 57 | #ASM = c:\bin\masm400 | ||
| 58 | #ASM = masm400 | ||
| 59 | ASM = masm | ||
| 60 | AFLAGS = -Mx -t -DI386 -DNoBugMode $(HIFLAG) | ||
| 61 | ADFLAGS = -Mx -t -DI386 $(HIFLAG) | ||
| 62 | AINC = -i..\emm | ||
| 63 | |||
| 64 | # Defines for C Compiler | ||
| 65 | C = cl | ||
| 66 | CFLAGS =/AS /G2 /Oat /Gs /Ze /Zl /Fc /c | ||
| 67 | |||
| 68 | # Definitions for linker for old style .exe files | ||
| 69 | #LINK = c:\bin\link | ||
| 70 | #LINK = link | ||
| 71 | LINK = link | ||
| 72 | LFLAGS = /NOI | ||
| 73 | |||
| 74 | # Definitions for .COM generation | ||
| 75 | CONVERT = c:\dos\exe2bin | ||
| 76 | #CONVERT = exe2bin | ||
| 77 | |||
| 78 | # Rules for generating object and linker response and definition files | ||
| 79 | .asm.obj: | ||
| 80 | $(ASM) $(AFLAGS) $(AINC) -p $*.asm; | ||
| 81 | |||
| 82 | .asm.lst: | ||
| 83 | $(ASM) -l -n $(AFLAGS) $(AINC) -p $*.asm; | ||
| 84 | |||
| 85 | #****************************************************************************** | ||
| 86 | # List of include files required | ||
| 87 | #****************************************************************************** | ||
| 88 | MEMMINC = ascii_sm.equ driver.equ pic_def.equ romstruc.equ romxbios.equ \ | ||
| 89 | desc.inc elim.inc emm386.inc instr386.inc kbd.inc loadall.inc \ | ||
| 90 | oemdep.inc page.inc vdmseg.inc vdmsel.inc vm386.inc mach_id.inc | ||
| 91 | |||
| 92 | |||
| 93 | #****************************************************************************** | ||
| 94 | # List of object files required | ||
| 95 | #****************************************************************************** | ||
| 96 | |||
| 97 | MEMMOBJ = memm386.obj elimfunc.obj init.obj allocmem.obj ppage.obj emmmes.obj \ | ||
| 98 | inittab.obj memmonf.obj rom_srch.obj i286.obj trapdef.obj \ | ||
| 99 | i386.obj tabdef.obj vmtrap.obj vminst.obj elimtrap.obj \ | ||
| 100 | vminit.obj moveb.obj em286ll.obj em386ll.obj retreal.obj \ | ||
| 101 | rrtrap.obj vdminit.obj initepg.obj errhndlr.obj maplin.obj \ | ||
| 102 | ekbd.obj util.obj initdeb.obj emm.obj emminit.obj mapdma.obj \ | ||
| 103 | iotrap.obj a20trap.obj oemproc.obj m_state.obj \ | ||
| 104 | shiphi.obj extpool.obj | ||
| 105 | |||
| 106 | COMOBJ = memmcom.obj memmonf.obj | ||
| 107 | |||
| 108 | BUGOBJ = memm386.obj elimfunc.obj init.obj allocmem.obj ppage.obj emmmes.obj \ | ||
| 109 | inittab.obj memmonf.obj rom_srch.obj i286.obj trapdef.obj \ | ||
| 110 | i386.obj tabdefD.obj vmtrapD.obj vminstD.obj elimtrap.obj \ | ||
| 111 | vminit.obj moveb.obj em286ll.obj em386ll.obj retreal.obj \ | ||
| 112 | rrtrap.obj vdminitD.obj initepg.obj errhndlr.obj maplin.obj \ | ||
| 113 | ekbd.obj util.obj initdebD.obj emmD.obj emminit.obj mapdma.obj \ | ||
| 114 | iotrap.obj a20trap.obj oemproc.obj kbd.obj print.obj m_state.obj | ||
| 115 | |||
| 116 | #****************************************************************************** | ||
| 117 | # List of libraries required | ||
| 118 | #****************************************************************************** | ||
| 119 | |||
| 120 | MEMMLIBS = ..\emm\emmlib.lib | ||
| 121 | |||
| 122 | BUGLIBS = ..\deb386\buglib.lib ..\emm\emmlib.lib | ||
| 123 | |||
| 124 | #****************************************************************************** | ||
| 125 | # Listing files | ||
| 126 | #****************************************************************************** | ||
| 127 | MEMMLST = memm386.lst elimfunc.lst init.lst ppage.lst allocmem.lst emmmes.lst \ | ||
| 128 | inittab.lst memmonf.lst rom_srch.lst i286.lst trapdef.obj \ | ||
| 129 | i386.lst tabdef.lst vmtrap.lst vminst.lst elimtrap.lst \ | ||
| 130 | vminit.lst moveb.lst em286ll.lst em386ll.lst retreal.lst \ | ||
| 131 | rrtrap.lst vdminit.lst initepg.lst errhndlr.lst maplin.lst \ | ||
| 132 | ekbd.lst util.lst initdeb.lst emm.lst emminit.lst mapdma.lst \ | ||
| 133 | iotrap.lst a20trap.lst memminc.lst oemproc.lst shiphi.lst \ | ||
| 134 | extpool.lst | ||
| 135 | |||
| 136 | COMLST = memmcom.lst memmonf.lst | ||
| 137 | |||
| 138 | BUGLST = memm386.lst elimfunc.lst init.lst allocmem.lst ppage.lst emmmes.lst \ | ||
| 139 | inittab.lst memmonf.lst rom_srch.lst i286.lst trapdef.lst \ | ||
| 140 | i386.lst tabdefD.lst vmtrapD.lst vminstD.lst elimtrap.lst \ | ||
| 141 | vminit.lst moveb.lst em286ll.lst em386ll.lst retreal.lst \ | ||
| 142 | rrtrap.lst vdminitD.lst initepg.lst errhndlr.lst maplin.lst \ | ||
| 143 | ekbd.lst util.lst initdebD.lst emmD.lst emminit.lst mapdma.lst \ | ||
| 144 | iotrap.lst a20trap.lst kbd.lst emmincD.lst oemproc.lst | ||
| 145 | |||
| 146 | |||
| 147 | #****************************************************************************** | ||
| 148 | # MEMM targets | ||
| 149 | #****************************************************************************** | ||
| 150 | #emm386: emm386.exe emm386.com emm386d.exe | ||
| 151 | emm386: emm386.exe | ||
| 152 | |||
| 153 | # production version of EMM386 device driver | ||
| 154 | # | ||
| 155 | emm386.exe: $(MEMMOBJ) $(MEMMLIBS) emm386.lnk | ||
| 156 | $(LINK) $(LFLAGS) @emm386.lnk | ||
| 157 | del emm386.sys | ||
| 158 | ren emm386.exe emm386.sys | ||
| 159 | |||
| 160 | # EMM386.COM utility | ||
| 161 | # | ||
| 162 | #emm386.com: $(COMOBJ) emmcom.lnk | ||
| 163 | # $(LINK) $(LFLAGS) @emmcom.lnk | ||
| 164 | # $(CONVERT) emmcom.exe emm386.com | ||
| 165 | |||
| 166 | # debug version of EMM386 driver | ||
| 167 | # | ||
| 168 | #emm386d.exe: $(BUGOBJ) $(BUGLIBS) emm386d.lnk | ||
| 169 | # $(LINK) $(LFLAGS) @emm386d.lnk | ||
| 170 | |||
| 171 | #****************************************************************************** | ||
| 172 | # EMM386 driver i/f modules | ||
| 173 | #****************************************************************************** | ||
| 174 | |||
| 175 | memm386.obj: memm386.asm $(MEMMINC) | ||
| 176 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 177 | memm386.lst: memm386.asm $(MEMMINC) | ||
| 178 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 179 | |||
| 180 | elimfunc.obj: elimfunc.asm $(MEMMINC) | ||
| 181 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 182 | elimfunc.lst: elimfunc.asm $(MEMMINC) | ||
| 183 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 184 | |||
| 185 | init.obj: init.asm $(MEMMINC) | ||
| 186 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 187 | init.lst: init.asm $(MEMMINC) | ||
| 188 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 189 | |||
| 190 | allocmem.obj: allocmem.asm $(MEMMINC) | ||
| 191 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 192 | allocmem.lst: allocmem.asm $(MEMMINC) | ||
| 193 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 194 | |||
| 195 | rom_srch.obj: rom_srch.asm $(MEMMINC) | ||
| 196 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 197 | rom_srch.lst: rom_srch.asm $(MEMMINC) | ||
| 198 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 199 | |||
| 200 | inittab.obj inittab.lst: inittab.asm $(MEMMINC) | ||
| 201 | |||
| 202 | emmmes.obj emmmes.lst: emmmes.asm $(MEMMINC) | ||
| 203 | |||
| 204 | extpool.obj extpool.lst: extpool.asm $(MEMMINC) | ||
| 205 | |||
| 206 | shiphi.obj shiphi.lst: shiphi.asm $(MEMMINC) | ||
| 207 | |||
| 208 | m_state.obj m_state.lst: m_state.asm $(MEMMINC) | ||
| 209 | |||
| 210 | ppage.obj ppage.lst: ppage.asm $(MEMMINC) ..\emm\emmdef.inc | ||
| 211 | |||
| 212 | #****************************************************************************** | ||
| 213 | # VDM modules | ||
| 214 | #****************************************************************************** | ||
| 215 | |||
| 216 | vdminit.obj vdminit.lst: vdminit.asm $(MEMMINC) | ||
| 217 | |||
| 218 | i286.obj i286.lst: i286.asm $(MEMMINC) | ||
| 219 | |||
| 220 | i386.obj i386.lst: i386.asm $(MEMMINC) | ||
| 221 | |||
| 222 | trapdef.obj trapdef.lst: trapdef.asm $(MEMMINC) | ||
| 223 | |||
| 224 | tabdef.obj tabdef.lst: tabdef.asm $(MEMMINC) | ||
| 225 | |||
| 226 | vmtrap.obj vmtrap.lst: vmtrap.asm $(MEMMINC) | ||
| 227 | |||
| 228 | vminst.obj vminst.lst: vminst.asm $(MEMMINC) | ||
| 229 | |||
| 230 | elimtrap.obj: elimtrap.asm $(MEMMINC) ..\emm\emmdef.inc | ||
| 231 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 232 | elimtrap.lst: elimtrap.asm $(MEMMINC) ..\emm\emmdef.inc | ||
| 233 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 234 | |||
| 235 | iotrap.obj iotrap.lst: iotrap.asm $(MEMMINC) | ||
| 236 | |||
| 237 | initepg.obj: initepg.asm $(MEMMINC) | ||
| 238 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 239 | initepg.lst: initepg.asm $(MEMMINC) | ||
| 240 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 241 | |||
| 242 | vminit.obj vminit.lst: vminit.asm $(MEMMINC) | ||
| 243 | |||
| 244 | em286ll.obj em286ll.lst: em286ll.asm $(MEMMINC) | ||
| 245 | |||
| 246 | em386ll.obj em386ll.lst: em386ll.asm $(MEMMINC) | ||
| 247 | |||
| 248 | moveb.obj: moveb.asm $(MEMMINC) | ||
| 249 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 250 | moveb.lst: moveb.asm $(MEMMINC) | ||
| 251 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 252 | |||
| 253 | util.obj: util.asm $(MEMMINC) | ||
| 254 | $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 255 | util.lst: util.asm $(MEMMINC) | ||
| 256 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 257 | |||
| 258 | maplin.obj maplin.lst: maplin.asm $(MEMMINC) | ||
| 259 | |||
| 260 | a20trap.obj a20trap.lst: a20trap.asm $(MEMMINC) | ||
| 261 | |||
| 262 | oemproc.obj oemproc.lst: oemproc.asm $(MEMMINC) | ||
| 263 | |||
| 264 | rrtrap.obj rrtrap.lst: rrtrap.asm $(MEMMINC) | ||
| 265 | |||
| 266 | retreal.obj retreal.lst: retreal.asm $(MEMMINC) | ||
| 267 | |||
| 268 | errhndlr.obj errhndlr.lst: errhndlr.asm $(MEMMINC) | ||
| 269 | |||
| 270 | ekbd.obj ekbd.lst: ekbd.asm $(MEMMINC) | ||
| 271 | |||
| 272 | initdeb.obj initdeb.lst: initdeb.asm $(MEMMINC) | ||
| 273 | |||
| 274 | emminit.obj emminit.lst: emminit.asm $(MEMMINC) | ||
| 275 | |||
| 276 | emm.obj emm.lst: emm.asm $(MEMMINC) | ||
| 277 | |||
| 278 | mapdma.obj mapdma.lst: mapdma.c | ||
| 279 | $(C) /ASw /G2 /Oat /Gs /Ze /Zl /Fc /c mapdma.c | ||
| 280 | |||
| 281 | memminc.lst: memminc.asm $(MEMMINC) | ||
| 282 | $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 283 | |||
| 284 | #****************************************************************************** | ||
| 285 | # debug modules | ||
| 286 | #****************************************************************************** | ||
| 287 | |||
| 288 | #tabdefD.obj: tabdef.asm $(MEMMINC) | ||
| 289 | # $(ASM) $(ADFLAGS) $(AINC) tabdef.asm,tabdefD.obj; | ||
| 290 | #tabdefD.lst: tabdef.asm $(MEMMINC) | ||
| 291 | # $(ASM) -l -n $(ADFLAGS) $(AINC) tabdef.asm,tabdefD.obj,tabdefD.lst; | ||
| 292 | # | ||
| 293 | #vminstD.obj: vminst.asm $(MEMMINC) | ||
| 294 | # $(ASM) $(ADFLAGS) $(AINC) vminst.asm,vminstD.obj; | ||
| 295 | #vminstD.lst: vminst.asm $(MEMMINC) | ||
| 296 | # $(ASM) -l -n $(ADFLAGS) $(AINC) vminst.asm,vminstD.obj,vminstD.lst; | ||
| 297 | |||
| 298 | #vmtrapD.obj: vmtrap.asm $(MEMMINC) | ||
| 299 | # $(ASM) $(ADFLAGS) $(AINC) vmtrap.asm,vmtrapD.obj; | ||
| 300 | #vmtrapD.lst: vmtrap.asm $(MEMMINC) | ||
| 301 | # $(ASM) -l -n $(ADFLAGS) $(AINC) vmtrap.asm,vmtrapD.obj,vmtrapD.lst; | ||
| 302 | # | ||
| 303 | #vdminitD.obj: vdminit.asm $(MEMMINC) | ||
| 304 | # $(ASM) $(ADFLAGS) $(AINC) vdminit.asm,vdminitD.obj; | ||
| 305 | #vdminitD.lst: vdminit.asm $(MEMMINC) | ||
| 306 | # $(ASM) -l -n $(ADFLAGS) $(AINC) vdminit.asm,vdminitD.obj,vdminitD.lst; | ||
| 307 | |||
| 308 | #initdebD.obj: initdeb.asm $(MEMMINC) | ||
| 309 | # $(ASM) $(ADFLAGS) $(AINC) initdeb.asm,initdebD.obj; | ||
| 310 | #initdebD.lst: initdeb.asm $(MEMMINC) | ||
| 311 | # $(ASM) -l -n $(ADFLAGS) $(AINC) initdeb.asm,initdebD.obj,initdebD.lst; | ||
| 312 | |||
| 313 | #emmD.obj: emm.asm $(MEMMINC) | ||
| 314 | # $(ASM) $(ADFLAGS) $(AINC) emm.asm,emmD.obj; | ||
| 315 | #emmD.lst: emm.asm $(MEMMINC) | ||
| 316 | # $(ASM) -l -n $(ADFLAGS) $(AINC) emm.asm,emmD.obj,emmD.lst; | ||
| 317 | |||
| 318 | #kbd.obj kbd.lst: kbd.asm $(MEMMINC) | ||
| 319 | # $(ASM) $(ADFLAGS) $(AINC) -p $*.asm; | ||
| 320 | |||
| 321 | #print.obj print.lst: print.asm $(MEMMINC) | ||
| 322 | # $(ASM) $(ADFLAGS) $(AINC) -p $*.asm; | ||
| 323 | |||
| 324 | #memmincD.lst: memminc.asm $(MEMMINC) | ||
| 325 | # $(ASM) -l -n $(ADFLAGS) $(AINC) memminc.asm,memmincD.obj,memmincD.lst; | ||
| 326 | |||
| 327 | #****************************************************************************** | ||
| 328 | # EMM386.COM modules | ||
| 329 | #****************************************************************************** | ||
| 330 | |||
| 331 | #memmcom.obj: memmcom.asm | ||
| 332 | # $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 333 | #memmcom.lst: memmcom.asm | ||
| 334 | # $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 335 | |||
| 336 | #memmonf.obj: memmonf.asm memm_msg.inc | ||
| 337 | # $(ASM) $(AFLAGS) $(AINC) $*.asm; | ||
| 338 | #memmonf.lst: memmonf.asm memm_msg.inc | ||
| 339 | # $(ASM) -l -n $(AFLAGS) $(AINC) $*.asm; | ||
| 340 | |||
| 341 | |||
| 342 | |||
| 343 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MAPDMA.ASM b/v4.0/src/MEMM/MEMM/MAPDMA.ASM new file mode 100644 index 0000000..c1e1f4f --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAPDMA.ASM | |||
| @@ -0,0 +1,633 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MapDMA - Ensure all DMA transfers are physically contiguous | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MapDMA | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 18,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/18/86 Original | ||
| 27 | ; 07/02/86 0.03 Added check for ECX = 0 | ||
| 28 | ; 07/02/86 0.03 MapLinear added to set_selector | ||
| 29 | ; 07/06/86 0.04 Changed _pft386 to ptr to _pft386 array | ||
| 30 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; | ||
| 36 | ; This module ensures that EMM pages accessed by a DMA transfer (within | ||
| 37 | ; the EMM Page Frame) are physically contiguous in memory. This is accomplished | ||
| 38 | ; by physically relocating entire EMM pages so that all of the pages participating | ||
| 39 | ; in the DMA transfer are adjacent. As a first pass, pages that need to be | ||
| 40 | ; relocated will always be moved to the base address of extended memory (or | ||
| 41 | ; possibly hi memory if that option is selected). A four word array (DMA_Pages) | ||
| 42 | ; initialized by InitEPG will contain the actual 32 bit physical address of | ||
| 43 | ; the first four physical EMM page locations. Although this will decrease | ||
| 44 | ; the time necessary to search for potential relocation candidates, it could | ||
| 45 | ; also result in the relocation of all pages when a fewer number might suffice | ||
| 46 | ; (given a more elegant mapping scheme). | ||
| 47 | ; | ||
| 48 | ; Some transfers that will NOT require remapping are: | ||
| 49 | ; 1. The DMA transfer is entirely outside the EMM Page Frame | ||
| 50 | ; 2. The DMA transfer is entirely within one Page Frame Window | ||
| 51 | ; 3. The DMA transfer spans more than one Page Frame Window, but | ||
| 52 | ; the EMM pages currently residing there are already contiguous | ||
| 53 | ; 4. See number 4 below | ||
| 54 | ; | ||
| 55 | ; Some transfers that will result in an exception are: | ||
| 56 | ; 1. The DMA transfer spans more than one Page Frame Window, where | ||
| 57 | ; at least one (but not all) of the windows is currently unmapped. | ||
| 58 | ; 2. The DMA transfer spans more than one Page Frame Window, with | ||
| 59 | ; the same EMM page residing in more than one of the windows | ||
| 60 | ; 3. The DMA transfer spans more than one Page Frame Window, but there | ||
| 61 | ; is physically not enough contiguous memory in which to locate the | ||
| 62 | ; requested EMM Pages. (This could occur in the model where both | ||
| 63 | ; extended memory and hi memory combine to form the EMM pool) | ||
| 64 | ; 4. The DMA transfer includes memory outside the Page Frame, AND | ||
| 65 | ; INSIDE the Page Frame (unless the Page Frame Windows are currently | ||
| 66 | ; unmapped, in which case no relocation is necessary) | ||
| 67 | ; | ||
| 68 | ;****************************************************************************** | ||
| 69 | .lfcond ; list false conditionals | ||
| 70 | .386p | ||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; P U B L I C D E C L A R A T I O N S | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; | ||
| 76 | public MapDMA | ||
| 77 | public DMA_Pages | ||
| 78 | public DMA_PAGE_COUNT | ||
| 79 | |||
| 80 | page | ||
| 81 | ;****************************************************************************** | ||
| 82 | ; L O C A L C O N S T A N T S | ||
| 83 | ;****************************************************************************** | ||
| 84 | ; | ||
| 85 | include VDMseg.inc | ||
| 86 | include VDMsel.inc | ||
| 87 | include desc.inc | ||
| 88 | include page.inc | ||
| 89 | include instr386.inc | ||
| 90 | include vm386.inc | ||
| 91 | include emmdef.inc | ||
| 92 | ; | ||
| 93 | ;****************************************************************************** | ||
| 94 | ; E X T E R N A L R E F E R E N C E S | ||
| 95 | ;****************************************************************************** | ||
| 96 | ; | ||
| 97 | ABS0 segment use16 at 0000h | ||
| 98 | ABS0 ends | ||
| 99 | |||
| 100 | _DATA segment | ||
| 101 | |||
| 102 | extrn _page_frame_base:dword ; Page Table Entry pointers for windows 0-3 | ||
| 103 | extrn _pft386:word ; ptr to array of Page Table entries | ||
| 104 | ;extrn _current_map:byte ; current mapping register values | ||
| 105 | extrn PF_Base:word ; Base addr of page frame | ||
| 106 | extrn _total_pages:word ; total number of EMM pages | ||
| 107 | extrn Page_Dir:word | ||
| 108 | |||
| 109 | xfer_map dw 0 ; map of windows participating in DMA xfer | ||
| 110 | _DATA ends | ||
| 111 | |||
| 112 | _TEXT segment | ||
| 113 | |||
| 114 | extrn ErrHndlr:near | ||
| 115 | extrn MapLinear:near | ||
| 116 | |||
| 117 | _TEXT ends | ||
| 118 | |||
| 119 | ;****************************************************************************** | ||
| 120 | ; S E G M E N T D E F I N I T I O N | ||
| 121 | ;****************************************************************************** | ||
| 122 | ; | ||
| 123 | _DATA segment | ||
| 124 | |||
| 125 | ; | ||
| 126 | ; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386. | ||
| 127 | ; To access actual entry in pft386 you need to multiply index by 4. | ||
| 128 | ; If eight contingous 16k EMM pages are not available - the unavailable | ||
| 129 | ; entries are left at NULL_PAGE. | ||
| 130 | ; This array should be initialized at boot time. | ||
| 131 | ; | ||
| 132 | DMA_Pages dw 8 dup (NULL_PAGE) ; null for start | ||
| 133 | DMA_PAGE_COUNT dw 0 ; number of above initialised | ||
| 134 | |||
| 135 | _DATA ends | ||
| 136 | |||
| 137 | ;------------------------------------------------------------------------------ | ||
| 138 | _TEXT segment | ||
| 139 | |||
| 140 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 141 | page | ||
| 142 | ;****************************************************************************** | ||
| 143 | ; MapDMA - Relocate (if necessary) EMM pages to ensure that a DMA transfer | ||
| 144 | ; is contiguous | ||
| 145 | ; | ||
| 146 | ; ENTRY: Protected Mode Ring 0 | ||
| 147 | ; EAX = linear base address of DMA transfer | ||
| 148 | ; ECX = byte count of transfer | ||
| 149 | ; DGROUP:[_pft386] = ptr to dword array of ptrs for EMM Pages | ||
| 150 | ; DGROUP:[DMA_Pages] = array of EMM page addresses in 1st 64k (used for | ||
| 151 | ; relocating pages to contiguous physical memory) | ||
| 152 | ; | ||
| 153 | ; EXIT: Protected mode Ring 0 | ||
| 154 | ; EAX = physical base address for DMA transfer | ||
| 155 | ; DGROUP:_pft386[] = modified to reflect relocation of EMM pages | ||
| 156 | ; Page Table Entries modified to reflect relocation. | ||
| 157 | ; CY = CLEAR if exit address = entry address | ||
| 158 | ; CY = SET if exit address <> entry address (mapping was necessary) | ||
| 159 | ; | ||
| 160 | ; USED: EAX | ||
| 161 | ; Flags | ||
| 162 | ; STACK: | ||
| 163 | ;****************************************************************************** | ||
| 164 | MapDMA proc near | ||
| 165 | ; | ||
| 166 | PUSH_EBX | ||
| 167 | PUSH_EAX ; save original address | ||
| 168 | PUSH_ECX | ||
| 169 | PUSH_EDX | ||
| 170 | PUSH_EDI | ||
| 171 | PUSH_ESI | ||
| 172 | push es | ||
| 173 | ; | ||
| 174 | cld | ||
| 175 | ; | ||
| 176 | ; check for ECX = 0 | ||
| 177 | ; | ||
| 178 | jecxz nomap1 ; nomap out of jmp range | ||
| 179 | jmp short mDMA_domap | ||
| 180 | nomap1: | ||
| 181 | jmp nomap | ||
| 182 | ; | ||
| 183 | ; As a quick first check, let's see if this transfer is any where near the PF | ||
| 184 | ; | ||
| 185 | mDMA_domap: | ||
| 186 | mov ebx,eax ; get address | ||
| 187 | shr ebx,16 ; get rid of 64k | ||
| 188 | mov dx,[PF_Base] ; base address of Page Frame div 4 | ||
| 189 | mov di,dx ; save it | ||
| 190 | shr dx,12 ; divide by 64k | ||
| 191 | cmp bx,dx ; q: is it in PF? | ||
| 192 | jb nomap ; n: no mapping necessary | ||
| 193 | add di,0fffh ; plus 64k div 4 for end of PF | ||
| 194 | shr di,12 ; divide by 64k | ||
| 195 | cmp bx,di ; q: before end of PF? | ||
| 196 | ja nomap ; n: no mapping necessary | ||
| 197 | ; | ||
| 198 | push ax ; save lower 16 bits of addr | ||
| 199 | mov ebx,4000h ; window size | ||
| 200 | ; | ||
| 201 | ; build a map of windows used in this transfer | ||
| 202 | ; | ||
| 203 | mov [xfer_map],0 ; zero to start with | ||
| 204 | dec ecx ; stop at last byte | ||
| 205 | lloop: | ||
| 206 | call chk_loc ; mark this guy's location in the map | ||
| 207 | or ecx,ecx ; q: done? | ||
| 208 | jz chk_done ; y | ||
| 209 | cmp ecx,ebx ; n: q: is there a whole window left? | ||
| 210 | jae full_wind ; y: skip the adjustment | ||
| 211 | mov bx,cx ; n: just check what's left | ||
| 212 | full_wind: | ||
| 213 | sub ecx,ebx ; adjust count by window size | ||
| 214 | add ax,bx ; and base addr (let it wrap) | ||
| 215 | jmp lloop ; do the next one | ||
| 216 | chk_done: | ||
| 217 | pop ax ; restore base addr of transfer | ||
| 218 | shl [xfer_map],1 ; q: is the transfer outside the PF? | ||
| 219 | jnc in_PF ; n: entirely within Page Frame | ||
| 220 | ; | ||
| 221 | ; At least part of the transfer involves an area outside the Page Frame. | ||
| 222 | ; This is ok as long as all parts inside the Page Frame are currently unmapped. | ||
| 223 | ; | ||
| 224 | mov cx,[xfer_map] ; get the map values | ||
| 225 | xor si,si ; set up to check all windows | ||
| 226 | xor edx,edx ; clean out high bits | ||
| 227 | mov dx,[PF_Base] ; dx = address of window 0 | ||
| 228 | shl edx,4 ; make it 32 bits | ||
| 229 | mloop1: | ||
| 230 | shl cx,1 ; q: is this window involved? | ||
| 231 | jnc not_inv ; n: not involved but still more to check | ||
| 232 | call IsMapped ; q: is this page mapped? | ||
| 233 | jne excp ; y: exception (can't handle it) | ||
| 234 | not_inv: | ||
| 235 | add edx, 4000h ; n: update address of window | ||
| 236 | add si,4 ; and _page_frame_base index | ||
| 237 | or cx,cx ; q: any more to check? | ||
| 238 | jnz mloop1 ; y: check the next window | ||
| 239 | ; | ||
| 240 | nomap: jmp DMA_nomap ; don't need to relocate | ||
| 241 | ; | ||
| 242 | excp: jmp DMA_excp ; exception (can't deal with this) | ||
| 243 | ; | ||
| 244 | ; The DMA transfer is entirely within the Page Frame area. If the | ||
| 245 | ; physical location of the EMM pages (mapped into the windows participating | ||
| 246 | ; in the DMA transfer) are already contiguous, then don't do anything. | ||
| 247 | ; Otherwise, relocate them to the base area. | ||
| 248 | ; | ||
| 249 | ; eax >= [PF_Base] = linear base address of xfer | ||
| 250 | ; | ||
| 251 | in_PF: | ||
| 252 | mov bx,[xfer_map] ; get a copy of the map | ||
| 253 | shr bx,4 ; duplicate on the end | ||
| 254 | or [xfer_map],bx ; ... for wraparound | ||
| 255 | op32 | ||
| 256 | mov cx,ax ; ecx = base addr of xfer | ||
| 257 | op32 | ||
| 258 | shr cx,4 ; paragraph form | ||
| 259 | sub cx,[PF_Base] | ||
| 260 | shr cx,10 ; cx = starting window of transfer | ||
| 261 | shl [xfer_map],cl ; position on 1st window of transfer | ||
| 262 | and [xfer_map],0f7ffh ; only 1st 4 windows are valid | ||
| 263 | shl [xfer_map],1 ; we know there's at least one | ||
| 264 | or [xfer_map],cx ; save starting window number | ||
| 265 | mov bx,cx ; bx = starting window | ||
| 266 | shl bx,2 ; bx = double word index | ||
| 267 | mov cx,[xfer_map] ; get map back | ||
| 268 | les di,_page_frame_base[bx] ; es:di = page table pointer for window bx | ||
| 269 | and ax,3fffh ; get lower 14 bits | ||
| 270 | push ax ; save lower 14 bits of starting addr | ||
| 271 | op32 | ||
| 272 | mov ax,es:[di] ; get page table entry | ||
| 273 | and ax,0f000h ; get rid of lower 12 bits | ||
| 274 | push_eax ; save physical address | ||
| 275 | ; | ||
| 276 | ; bx = window number to check for contiguity | ||
| 277 | ; eax = physical address of EMM page mapped into previous window | ||
| 278 | ; cx = bit map of windows participating in the transfer | ||
| 279 | ; | ||
| 280 | c_chk: | ||
| 281 | shl cx,1 ; q: is the next window involved? | ||
| 282 | jnc DMA_addr ; n: no need to check any more | ||
| 283 | add bx,4 ; next window | ||
| 284 | and bx,0fh ; mod 16 | ||
| 285 | add ax,4000h ; next physically contiguous window | ||
| 286 | les di,_page_frame_base[bx] ; es:di = page table pointer for window bx | ||
| 287 | op32 | ||
| 288 | mov dx,es:[di] ; get page table entry | ||
| 289 | and dx,0f000h ; get rid of lower 12 bits | ||
| 290 | op32 | ||
| 291 | cmp ax,dx ; q: contiguous? | ||
| 292 | je c_chk ; y: check next window | ||
| 293 | ; | ||
| 294 | jmp DMA_reloc ; They were not contiguous, must relocate | ||
| 295 | DMA_addr: | ||
| 296 | pop_eax ; top part of actual address | ||
| 297 | pop dx ; get second half of actual address | ||
| 298 | or ax,dx ; form real address | ||
| 299 | jmp DMA_nomap ; don't need to map | ||
| 300 | ; | ||
| 301 | ; Relocate EMM pages mapped into the windows starting with the | ||
| 302 | ; low order bits of [xfer_map], for as many high bits of [xfer_map]. | ||
| 303 | ; The lower 14 bits of original address are still on the stack | ||
| 304 | ; | ||
| 305 | DMA_reloc: | ||
| 306 | pop_eax ; top part of actual address | ||
| 307 | mov bx,[xfer_map] ; get map | ||
| 308 | mov cx,bx ; copy it | ||
| 309 | and bx,3 ; bx = starting window number | ||
| 310 | xor di,di ; di = index into DMA_Pages | ||
| 311 | reloc_loop: | ||
| 312 | mov si,12 ; board index for _current_map | ||
| 313 | push cx ; save window map | ||
| 314 | mov cx,4 ; 4 boards | ||
| 315 | bloop: | ||
| 316 | ; WE NEED TO WORK ON THE DMA MORE | ||
| 317 | ; BUT int the mean time, ignore _current_map (Paul Chan) | ||
| 318 | ; mov dl,_current_map[bx+si] ; get mapping register value | ||
| 319 | shl dl,1 ; q: is it mapped? | ||
| 320 | jnc next_board ; n: try next board | ||
| 321 | mov dh,cl ; y: dh = board number | ||
| 322 | dec dh ; board is zero relative | ||
| 323 | shr dx,1 ; dx = EMM page number | ||
| 324 | cmp dx,[_total_pages] ; q: is this page in range? | ||
| 325 | jb found_page ; y: go relocate it | ||
| 326 | next_board: ; n: try next board | ||
| 327 | sub si,4 ; update index to _current_map | ||
| 328 | loop bloop ; do another | ||
| 329 | ; | ||
| 330 | ; If we ever get here, we've got a problem in the data structures, or | ||
| 331 | ; in the previous couple of hundred lines since we couldn't seem to locate | ||
| 332 | ; any pages occupying window bx (which should have generated an exception | ||
| 333 | ; long ago). In either case, we might just as well call it an exception. | ||
| 334 | excp2: jmp DMA_excp ; don't know what else to do | ||
| 335 | ; | ||
| 336 | ; At this point we have found the EMM page (= dx) occupying window bx. | ||
| 337 | ; di is the index into DMA_Pages that tells us the physical address of this | ||
| 338 | ; particular relocation area. Now we need to run through _pft386 and find | ||
| 339 | ; this address so we can swap him with page dx. If DMA_Pages contains -1, | ||
| 340 | ; then we just don't have the physically contiguous memory to get the job done. | ||
| 341 | ; | ||
| 342 | found_page: | ||
| 343 | push di ; save di | ||
| 344 | op32 | ||
| 345 | mov ax,DMA_Pages[di] ; get addr of relocation area | ||
| 346 | op32 | ||
| 347 | or ax,ax ; q: -1? | ||
| 348 | js excp2 ; y: not enough contig memory | ||
| 349 | mov cx,[_total_pages] ; number of entries in _pft386 | ||
| 350 | mov si,-4 ; index into _pft386 | ||
| 351 | add si,[_pft386] ; si = ptr for _pft386 array | ||
| 352 | floop: | ||
| 353 | add si,4 ; point to next entry | ||
| 354 | op32 | ||
| 355 | mov di,[si] ; get pft entry | ||
| 356 | and di,0f000h ; get rid of low 12 bits | ||
| 357 | op32 | ||
| 358 | cmp di,ax ; q: did we find who's there? | ||
| 359 | loopne floop ; n: keep looking | ||
| 360 | jne excp2 ; whoops, nobody was using it | ||
| 361 | ; | ||
| 362 | ; si = ptr to EMM page currently using our relocation area. | ||
| 363 | ; Swap it with EMM page # dx | ||
| 364 | ; | ||
| 365 | mov di,dx ; page number in window | ||
| 366 | shl di,2 ; offset for _pft386 | ||
| 367 | add di,[_pft386] ; di -> EMM page#dx entry | ||
| 368 | cmp di,si ; q: was it us all along? | ||
| 369 | je no_swap ; y: don't need to move it | ||
| 370 | op32 | ||
| 371 | mov dx,[di] ; PTE for this page | ||
| 372 | and dx,0f000h ; get rid of low 12 bits | ||
| 373 | ; | ||
| 374 | ; DS:SI -> relocation page entry in _pft386 | ||
| 375 | ; DS:DI -> EMM page # dx entry in _pft386 | ||
| 376 | ; check to see if we have already relocated this guy once. If so, that | ||
| 377 | ; implies that the same EMM page is mapped into more than one window. | ||
| 378 | ; Since there is no way (without scratch buffers) to make that contiguous, | ||
| 379 | ; we will just abort. | ||
| 380 | ; | ||
| 381 | op32 | ||
| 382 | cmp dx,[DMA_Pages] ; q: have we already relocated it? | ||
| 383 | jb no_dup ; n: ok | ||
| 384 | op32 | ||
| 385 | cmp dx,ax ; q: is it in the relocation area? | ||
| 386 | jb excp2 ; y: sorry | ||
| 387 | no_dup: | ||
| 388 | op32 | ||
| 389 | and [si],0fffh ; preserve his 12 bits | ||
| 390 | dw 0 | ||
| 391 | op32 | ||
| 392 | or [si],dx ; move in his new address | ||
| 393 | op32 | ||
| 394 | and [di],0fffh ; now do the same thing | ||
| 395 | dw 0 ; for the page in the window | ||
| 396 | op32 | ||
| 397 | or [di],ax ; fix up his address | ||
| 398 | ; | ||
| 399 | ; swap pages residing at addresses eax and edx | ||
| 400 | ; | ||
| 401 | push_eax ; save address in window | ||
| 402 | push ds | ||
| 403 | mov di,MBSRC_GSEL ; source selector | ||
| 404 | call set_selector ; set to address eax | ||
| 405 | mov es,di | ||
| 406 | mov di,MBTAR_GSEL ; destination selector | ||
| 407 | op32 | ||
| 408 | mov ax,dx ; destination | ||
| 409 | call set_selector ; set up selector | ||
| 410 | mov ds,di | ||
| 411 | mov cx,1000h ; 16k bytes (4 at a time) | ||
| 412 | xor di,di ; initialize index | ||
| 413 | sloop: | ||
| 414 | op32 | ||
| 415 | mov ax,es:[di] ; get a word from dest. | ||
| 416 | op32 | ||
| 417 | xchg ax,ds:[di] ; swap with source | ||
| 418 | op32 | ||
| 419 | stosw ; store in dest. | ||
| 420 | loop sloop ; do the next one | ||
| 421 | ; | ||
| 422 | pop ds | ||
| 423 | pop_eax ; restore physical address | ||
| 424 | |||
| 425 | no_swap: | ||
| 426 | |||
| 427 | |||
| 428 | pop di ; index into DMA_Pages | ||
| 429 | add di,4 ; update index | ||
| 430 | pop cx ; window map | ||
| 431 | inc bx ; next window number | ||
| 432 | and bx,3 ; mod 4 | ||
| 433 | shl cx,1 ; q: any left? | ||
| 434 | jnc fix_pte ; n: done relocating | ||
| 435 | jmp reloc_loop ; y: relocate the next page | ||
| 436 | fix_pte: | ||
| 437 | ; | ||
| 438 | ; Now set all 4 entries in page table. Rather than try to figure out exactly | ||
| 439 | ; which entries in here have changed, we will reset all entries shown as | ||
| 440 | ; being "mapped" by _current_map. Unmapped entries shouldn't have changed. | ||
| 441 | ; | ||
| 442 | mov cx,15 ; start at last entry | ||
| 443 | ploop: | ||
| 444 | mov si,cx ; copy index | ||
| 445 | ; mov bl,_current_map[si] ; get current_map entry | ||
| 446 | shl bl,1 ; q: is it mapped? | ||
| 447 | jnc pte_not_mapped ; n: try next | ||
| 448 | mov bh,cl ; copy index number | ||
| 449 | shr bh,2 ; get board number | ||
| 450 | shr bx,1 ; bx = emm page number | ||
| 451 | cmp bx,[_total_pages] ; q: in range? | ||
| 452 | jae pte_not_mapped ; n: try next | ||
| 453 | shl bx,2 ; y: index into _pft386 | ||
| 454 | add bx,[_pft386] ; ptr into _pft386 | ||
| 455 | op32 | ||
| 456 | mov ax,[bx] ; y: get pte value | ||
| 457 | and ax,0f000h ; get rid of lower 12 bits | ||
| 458 | mov si,cx ; get index number | ||
| 459 | and si,3 ; get window number | ||
| 460 | shl si,2 ; 32 bit index | ||
| 461 | les di,_page_frame_base[si] ; pointer to page table entry | ||
| 462 | or ax,P_AVAIL ; set access bits | ||
| 463 | op32 | ||
| 464 | stosw ; set 1st Page Table Entry | ||
| 465 | |||
| 466 | add_eax_ 1000h ; 2nd 386 page | ||
| 467 | op32 | ||
| 468 | stosw ; set 2nd Page Table Entry | ||
| 469 | |||
| 470 | add_eax_ 1000h ; 3rd 386 page | ||
| 471 | op32 | ||
| 472 | stosw ; set 3rd Page Table Entry | ||
| 473 | |||
| 474 | add_eax_ 1000h ; 4th 386 page | ||
| 475 | op32 | ||
| 476 | stosw ; set 4th Page Table Entry | ||
| 477 | pte_not_mapped: | ||
| 478 | dec cx ; q: done with _current_map? | ||
| 479 | jns ploop ; n: keep going | ||
| 480 | |||
| 481 | ; | ||
| 482 | ; reload CR3 to flush TLB | ||
| 483 | ; | ||
| 484 | db 66h | ||
| 485 | mov ax,[Page_Dir] ; mov EAX,dword ptr [Page_Dir] | ||
| 486 | db 0Fh,22h,18h ; mov CR3,EAX | ||
| 487 | op32 | ||
| 488 | mov ax,[DMA_Pages] ; get physical address to return | ||
| 489 | pop dx ; don't forget about the lower 14 bits | ||
| 490 | or ax,dx | ||
| 491 | ; | ||
| 492 | ; eax = physical address for DMA transfer | ||
| 493 | ; | ||
| 494 | DMA_nomap: | ||
| 495 | pop es | ||
| 496 | POP_ESI | ||
| 497 | POP_EDI | ||
| 498 | POP_EDX | ||
| 499 | POP_ECX | ||
| 500 | POP_EBX ; get original eax | ||
| 501 | clc ; assume they're the same | ||
| 502 | OP32 | ||
| 503 | cmp ax,bx ; q: did we have to map? | ||
| 504 | je cy_noset ; n: don't set carry | ||
| 505 | stc ; y: set carry | ||
| 506 | cy_noset: | ||
| 507 | POP_EBX | ||
| 508 | ; | ||
| 509 | ret | ||
| 510 | DMA_excp: | ||
| 511 | mov ax,ExcpErr | ||
| 512 | mov bx,ErrDMA | ||
| 513 | jmp ErrHndlr ; don't come back | ||
| 514 | |||
| 515 | MapDMA endp | ||
| 516 | |||
| 517 | |||
| 518 | page | ||
| 519 | ;****************************************************************************** | ||
| 520 | ; IsMapped - Check whether or not a window is unmapped | ||
| 521 | ; | ||
| 522 | ; ENTRY: Protected Mode Ring 0 | ||
| 523 | ; si = window number * 4 | ||
| 524 | ; edx = physical address of Page Frame Window | ||
| 525 | ; DGROUP:[_page_frame_base] = array of ptrs to page table entries | ||
| 526 | ; | ||
| 527 | ; EXIT: Protected mode Ring 0 | ||
| 528 | ; ZF = unmapped | ||
| 529 | ; NZF= mapped | ||
| 530 | ; | ||
| 531 | ; USED: di,ebx,es | ||
| 532 | ; Flags | ||
| 533 | ; STACK: | ||
| 534 | ;****************************************************************************** | ||
| 535 | isMapped proc near | ||
| 536 | les di,_page_frame_base[si] ; es:di = addr of page table entry | ||
| 537 | op32 | ||
| 538 | mov bx,es:[di] ; ebx = page table entry for window | ||
| 539 | and bx,0f000h ; mask off low order 12 bits | ||
| 540 | op32 | ||
| 541 | cmp bx,dx ; q: is it mapped to itself (unmapped)? | ||
| 542 | ret | ||
| 543 | isMapped endp | ||
| 544 | |||
| 545 | |||
| 546 | page | ||
| 547 | ;****************************************************************************** | ||
| 548 | ; chk_loc - Check the location of a given address and update map accordingly | ||
| 549 | ; | ||
| 550 | ; ENTRY: Protected Mode Ring 0 | ||
| 551 | ; eax = physical address to check | ||
| 552 | ; DGROUP:[xfer_map] = map of addresses used in this transfer | ||
| 553 | ; bit 16 indicates an address outside the PF | ||
| 554 | ; bits 15-12 correspond to windows 0-3 resp. | ||
| 555 | ; | ||
| 556 | ; EXIT: Protected mode Ring 0 | ||
| 557 | ; DGROUP:[xfer_map] = updated as necessary | ||
| 558 | ; | ||
| 559 | ; USED: none | ||
| 560 | ; Flags | ||
| 561 | ; STACK: | ||
| 562 | ;****************************************************************************** | ||
| 563 | chk_loc proc near | ||
| 564 | push_eax ; save address | ||
| 565 | push cx | ||
| 566 | ; | ||
| 567 | mov ch,80h ; set high bit (outside indicator) | ||
| 568 | op32 | ||
| 569 | shr ax,4 ; put in paragraph form | ||
| 570 | sub ax,[PF_Base] ; make it relative to base of Page Frame | ||
| 571 | jb outside ; outside of page frame | ||
| 572 | op32 | ||
| 573 | shr ax,10 ; ax = window number | ||
| 574 | cmp_eax_ 3 ; q: inside Page Frame? | ||
| 575 | ja outside ; n: outside | ||
| 576 | mov cl,al ; | ||
| 577 | inc cl ; skip over outside bit | ||
| 578 | shr ch,cl | ||
| 579 | outside: | ||
| 580 | xor cl,cl ; clear lower byte | ||
| 581 | or [xfer_map],cx | ||
| 582 | ; | ||
| 583 | pop cx | ||
| 584 | pop_eax | ||
| 585 | ret | ||
| 586 | chk_loc endp | ||
| 587 | page | ||
| 588 | ;****************************************************************************** | ||
| 589 | ; set_selector - set up a selector address/attrib | ||
| 590 | ; | ||
| 591 | ; ENTRY: EAX = address for GDT selector | ||
| 592 | ; DI = GDT selector | ||
| 593 | ; EXIT: selector at ES:DI is writeable data segment,64k long and points | ||
| 594 | ; to desired address. | ||
| 595 | ; | ||
| 596 | ;****************************************************************************** | ||
| 597 | set_selector proc near | ||
| 598 | ; | ||
| 599 | PUSH_EAX | ||
| 600 | push di | ||
| 601 | push es | ||
| 602 | ; | ||
| 603 | call MapLinear | ||
| 604 | ; | ||
| 605 | and di,NOT 07h ; just in case... GDT entry | ||
| 606 | push GDTD_GSEL | ||
| 607 | pop es ; ES:DI -> selector entry | ||
| 608 | ; | ||
| 609 | mov es:[di+2],ax ; low word of base address | ||
| 610 | OP32 | ||
| 611 | shr ax,16 ; AX = high word of address | ||
| 612 | mov es:[di+4],al ; low byte of high word of address | ||
| 613 | xor al,al ; clear limit/G bit | ||
| 614 | mov es:[di+6],ax ; set high byte of high word of addr | ||
| 615 | ; and high nibble of limit/G bit | ||
| 616 | ; | ||
| 617 | mov ax,0FFFFh | ||
| 618 | mov es:[di],ax ; set limit to 64k | ||
| 619 | ; | ||
| 620 | mov al,D_DATA0 ; writeable DATA seg / ring 0 | ||
| 621 | mov es:[di+5],al | ||
| 622 | ; | ||
| 623 | pop es | ||
| 624 | pop di | ||
| 625 | POP_EAX | ||
| 626 | ret | ||
| 627 | ; | ||
| 628 | set_selector endp | ||
| 629 | |||
| 630 | _TEXT ends ; end of segment | ||
| 631 | ; | ||
| 632 | end ; end of module | ||
| 633 | |||
diff --git a/v4.0/src/MEMM/MEMM/MAPDMA.C b/v4.0/src/MEMM/MEMM/MAPDMA.C new file mode 100644 index 0000000..7aae10d --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAPDMA.C | |||
| @@ -0,0 +1,425 @@ | |||
| 1 | |||
| 2 | |||
| 3 | /* MAPDMA.C - Ensures DMA Xfer area is physically contiguous. Swaps pages | ||
| 4 | * if necessary. | ||
| 5 | * | ||
| 6 | * Date Author Comments | ||
| 7 | 8/12/88 JHB updated comments, checking for sufficient pages | ||
| 8 | available in DMA_Pages[] before remappping | ||
| 9 | |||
| 10 | 8/18/88 JHB if incoming parameters appear to be wrong or | ||
| 11 | if any unmapped page found in the transfer area assume | ||
| 12 | the Address and Count registers do not have valid values | ||
| 13 | and hence return without swapping pages. | ||
| 14 | Removed IFDEF DEBUG code | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define HEX4K 0x1000 | ||
| 18 | #define HEX16K 0x4000L | ||
| 19 | #define HEX64K 0x10000 | ||
| 20 | #define HEX128K 0x20000 | ||
| 21 | #define HEX256K 0x40000L | ||
| 22 | #define HEX640K 0xA0000L | ||
| 23 | #define HEX1MB 0x100000L | ||
| 24 | |||
| 25 | #define ALIGN128K ~0x1FFFFL | ||
| 26 | #define ALIGN64K ~0x0FFFFL | ||
| 27 | #define ALIGN16K ~0x03FFFL | ||
| 28 | |||
| 29 | #define MAX_PHYS_PAGES 40 | ||
| 30 | |||
| 31 | /* macros | ||
| 32 | * PT(a) - pte from index a | ||
| 33 | * INDEX(a) - index from Linear Adr | ||
| 34 | * OFFSET(a) - offset from Linear Adr | ||
| 35 | * LIN2PHY(l) - Physical Adr from Linear Adr | ||
| 36 | * DosPhyPage - consider 16K pages from 0 to 1MB. Let Page at 256K be page 0. | ||
| 37 | * DOSPHYPAGE(a) - DosPhyPage for Adr in 1 MB range | ||
| 38 | * PFT(a) - pick up ith entry in pft386[] | ||
| 39 | */ | ||
| 40 | |||
| 41 | #define PT(a) (GetPteFromIndex((a))) | ||
| 42 | #define INDEX(a) ((((long)a)>>12) & 0x3FF) | ||
| 43 | #define OFFSET(a) (((long)a) & 0xFFF) | ||
| 44 | #define LIN2PHY(l) ((PT(INDEX(l)) & ~0xFFFL)+(long)OFFSET(l)) | ||
| 45 | #define DOSPHYPAGE(a) (((a)>>14)-16) | ||
| 46 | #define PFT(a) (*(long *)(pft386+a)) | ||
| 47 | struct mappable_page { | ||
| 48 | unsigned short page_seg; /* segment of physical page */ | ||
| 49 | unsigned short physical_page; /* physical page number */ | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* Xlates DosPhyPage into an index in mappable_pages[]. */ | ||
| 53 | extern char EMM_MPindex[]; /* index from 4000H to 10000H in steps of 16K */ | ||
| 54 | extern struct mappable_page mappable_pages[]; | ||
| 55 | extern long *pft386; | ||
| 56 | extern unsigned DMA_Pages[]; | ||
| 57 | extern DMA_PAGE_COUNT; /* size of DMA_Pages[] */ | ||
| 58 | extern unsigned physical_page_count; | ||
| 59 | |||
| 60 | /* routines imported from elimtrap.asm */ | ||
| 61 | extern long GetPte(); /* get a PT entry given index */ | ||
| 62 | extern SetPte(); /* set a PT entry */ | ||
| 63 | extern unsigned GetCRSEntry(); /* get CurRegSet entry for given EmmPhyPage */ | ||
| 64 | extern long GetDMALinAdr(); /* Get Linear Adr for the DMA buffer */ | ||
| 65 | extern Exchange16K(); /* exchange page contents */ | ||
| 66 | extern FatalError(); | ||
| 67 | |||
| 68 | /* forward declarations */ | ||
| 69 | long GetPteFromIndex(); | ||
| 70 | |||
| 71 | /* | ||
| 72 | * SwapDMAPages() | ||
| 73 | * FromAdr - DMA Xfer addr | ||
| 74 | * Len - Xfer length | ||
| 75 | * bXfer - 0 for byte transfer, 1 for word transfer | ||
| 76 | * | ||
| 77 | * Check whether the DMA Xfer area starting at FromAdr is contiguous in | ||
| 78 | * physical memory. If it isn't, make it contiguous by exchanging pages | ||
| 79 | * with the DMA buffer. | ||
| 80 | */ | ||
| 81 | |||
| 82 | long SwapDMAPages(FromAdr, Len, bXfer) | ||
| 83 | long FromAdr, Len; | ||
| 84 | unsigned bXfer; | ||
| 85 | { | ||
| 86 | unsigned Index, Offset, /* components of a PTE */ | ||
| 87 | n4KPages, /* # of 4K Pages involved in the DMA transfer */ | ||
| 88 | PhyPages[8], /* Emm Phy page numbers involved in the DMA transfer | ||
| 89 | atmost 8.*/ | ||
| 90 | DMAPageK, /* kth DMA Page - start exchanging pages from here */ | ||
| 91 | Page, MPIndex; | ||
| 92 | |||
| 93 | long FromAdr16K, /* FromAdr rounded down to 16K boundary */ | ||
| 94 | FromAdr64_128K, /* FromAdr rounded down to 64/128K boundary */ | ||
| 95 | ToAdr, /* Last Byte for the DMA trasfer */ | ||
| 96 | ToAdr16K, /* ToAdr rounded down to 16K boundary */ | ||
| 97 | ExpectedAdr, | ||
| 98 | PgFrame, /* PgFrame Address */ | ||
| 99 | First64_128K_Adr, Last64_128K_Adr,/* First and Last 4K page aligned on a 64/128 boundary */ | ||
| 100 | Adr, PhyAdr, LinAdr; | ||
| 101 | |||
| 102 | int i, j, k, bSwap, | ||
| 103 | n16KPages; /* # of 16K Pages involved in the DMA transfer */ | ||
| 104 | |||
| 105 | |||
| 106 | if (FromAdr < HEX256K || FromAdr >= HEX1MB) | ||
| 107 | return LIN2PHY(FromAdr); /* not in the EMM area */ | ||
| 108 | |||
| 109 | /* Since the Address and count register are programmed a byte at a time | ||
| 110 | * they might have invalid values in them (because of left overs). | ||
| 111 | * If invalid parameters, i.e. Xfer area crosses 64K or 128K boundary,or count | ||
| 112 | * is invalid or the DMA Xfer area has unmapped pages - just return. | ||
| 113 | */ | ||
| 114 | if ((!bXfer && (FromAdr + Len) > ((FromAdr & ALIGN64K) + HEX64K)) || | ||
| 115 | (bXfer && (FromAdr + Len) > ((FromAdr & ALIGN128K) + HEX128K)) || | ||
| 116 | (!bXfer && Len > HEX64K) || (bXfer && Len > HEX128K)) | ||
| 117 | return FromAdr; /* assume DMA registers not programmed yet */ | ||
| 118 | |||
| 119 | /* initialise PhyPages[] - unequal negative values */ | ||
| 120 | for (i = 0; i < 8; i++) | ||
| 121 | PhyPages[i] = -(i+1); | ||
| 122 | |||
| 123 | |||
| 124 | /* The DMA buffer is part of the Emm pool. | ||
| 125 | * Hence we can only swap pages which are 16K in size. Hence calculate | ||
| 126 | * n16KPages - # of 16K pages involved in the transfer. | ||
| 127 | |||
| 128 | * ToAdr - Linear Address of the last byte where the DMA transfer | ||
| 129 | * is to take place | ||
| 130 | */ | ||
| 131 | ToAdr = FromAdr + Len - 1L; | ||
| 132 | FromAdr16K = FromAdr & ALIGN16K; | ||
| 133 | ToAdr16K = ToAdr & ALIGN16K; | ||
| 134 | n16KPages = ((ToAdr16K - FromAdr16K)>>14) + 1; /* (ToAdr16K-FromAdr16K)/HEX16K + 1 */ | ||
| 135 | |||
| 136 | /* If any unmapped page in the transfer area - assume DMA registers not | ||
| 137 | * fully programmed yet | ||
| 138 | */ | ||
| 139 | for (i = 0, Adr = FromAdr16K; Adr <= ToAdr16K; Adr += HEX16K, i++) { | ||
| 140 | MPIndex = EMM_MPindex[DOSPHYPAGE(Adr)]; | ||
| 141 | if (MPIndex == -1) /* Adr not mappable */ | ||
| 142 | return FromAdr; | ||
| 143 | else { | ||
| 144 | PhyPages[i] = GetCRSEntry(mappable_pages[MPIndex].physical_page); | ||
| 145 | if (PhyPages[i] == -1) /* Adr not mapped currently */ | ||
| 146 | return FromAdr; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | for (j = 0; j < i; j++) { | ||
| 151 | Page = PhyPages[j]; | ||
| 152 | for (k = j+1; k < i; k++) { | ||
| 153 | if (PhyPages[k] == Page) | ||
| 154 | FatalError("SwapDMAPages : Two Emm pages mapped to same logical page in the xfer area"); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | /* No unmapped page in the transfer area. Assume the Address and count registers | ||
| 159 | * have meaningful values in them. | ||
| 160 | */ | ||
| 161 | Index = INDEX(FromAdr); | ||
| 162 | PgFrame = PT(Index) >> 12; | ||
| 163 | Offset = OFFSET(FromAdr); | ||
| 164 | PhyAdr = (((long)PgFrame) << 12) + Offset; | ||
| 165 | |||
| 166 | if (Offset + Len <= HEX4K) /* within a page */ | ||
| 167 | return PhyAdr; | ||
| 168 | |||
| 169 | /* calculate # of 4K pages involved in the DMA transfer */ | ||
| 170 | |||
| 171 | n4KPages = ((Offset + Len)>>12) + 1; /* (Offset+Len)/4096K + 1 */ | ||
| 172 | if (((Offset + Len) % HEX4K) == 0) | ||
| 173 | n4KPages--; | ||
| 174 | |||
| 175 | /* see if these n4KPages are physically contiguous */ | ||
| 176 | bSwap = 0; | ||
| 177 | for (i = 1; i < n4KPages; i++) { | ||
| 178 | if ((PT(Index + i)>>12) != (PgFrame + i)) { | ||
| 179 | bSwap = 1; | ||
| 180 | break; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Suppose the Xfer area is physically contiguous. We may still need to swap | ||
| 185 | * pages with the DMA buffer if the physical pages straddle a 64K/128K boundary | ||
| 186 | * (the DMA will wrap around in this case). DOS would have tried to fix this | ||
| 187 | * but it would have split the Linear Address - this is of very little use. | ||
| 188 | * | ||
| 189 | * if (!bSwap && straddling 64/128K boundary) set bSwap; | ||
| 190 | */ | ||
| 191 | if (!bSwap) { /* the DMA Pages are contiguous, any straddling ? */ | ||
| 192 | if (!bXfer) { /* byte transfer */ | ||
| 193 | First64_128K_Adr = PT(Index) & ALIGN64K; | ||
| 194 | Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN64K; | ||
| 195 | } | ||
| 196 | else { /* word transfer */ | ||
| 197 | First64_128K_Adr = PT(Index) & ALIGN128K; | ||
| 198 | Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN128K; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (First64_128K_Adr != Last64_128K_Adr) | ||
| 202 | bSwap = 1; | ||
| 203 | } | ||
| 204 | |||
| 205 | if (!bSwap) | ||
| 206 | return PhyAdr; | ||
| 207 | |||
| 208 | /* The DMA transfer area is not contiguous. The DMA buffer is part of the Emm | ||
| 209 | * pool. Hence we can only swap pages which are 16K in size. n16KPages is the | ||
| 210 | * # of 16K pages involved in the transfer. | ||
| 211 | */ | ||
| 212 | |||
| 213 | /* Round down FromAdr to 64/128K boundary */ | ||
| 214 | if (bXfer) /* word transfer ? */ | ||
| 215 | FromAdr64_128K = FromAdr & ALIGN128K; /* Align on 128K boundary */ | ||
| 216 | else | ||
| 217 | FromAdr64_128K = FromAdr & ALIGN64K; /* Align on 64K boundary */ | ||
| 218 | |||
| 219 | /* Swap pages so that the DMA Xfer area is physically contiguous. | ||
| 220 | |||
| 221 | | | | | | ||
| 222 | FromAdr ->| | | | | ||
| 223 | | | | | | ||
| 224 | | | | | | ||
| 225 | FromAdr16K ->| | - - - DMAPage[k] -->| | | ||
| 226 | | | | | | ||
| 227 | | | | | | ||
| 228 | FromAdr64_128k-| | DMAPage[0] -->| | | ||
| 229 | ---------- ---------- | ||
| 230 | |||
| 231 | DMA transfer area starts at FromAdr. | ||
| 232 | Map kth DMA page to FromAdr16K and so on until all the transfer area is mapped | ||
| 233 | |||
| 234 | */ | ||
| 235 | |||
| 236 | /* Linear Adr of user page which has to be relocated */ | ||
| 237 | LinAdr = FromAdr16K; | ||
| 238 | |||
| 239 | /* corresponding DMA Page - k value in the above figure */ | ||
| 240 | DMAPageK = (FromAdr16K - FromAdr64_128K) >> 14; | ||
| 241 | |||
| 242 | ExpectedAdr = PFT(DMA_Pages[DMAPageK]); | ||
| 243 | |||
| 244 | if (DMAPageK + n16KPages > DMA_PAGE_COUNT) | ||
| 245 | FatalError("Insufficient DMA pages in the DMA Buffer"); | ||
| 246 | |||
| 247 | for (k = DMAPageK; k < DMAPageK + n16KPages; k++, LinAdr += HEX16K, | ||
| 248 | ExpectedAdr += HEX16K) { | ||
| 249 | /* Already mapped correctly ? */ | ||
| 250 | if (LIN2PHY(LinAdr) == ExpectedAdr) | ||
| 251 | continue; | ||
| 252 | /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page */ | ||
| 253 | SwapAPage(LinAdr, k); | ||
| 254 | } | ||
| 255 | |||
| 256 | return LIN2PHY(FromAdr); | ||
| 257 | } | ||
| 258 | |||
| 259 | /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page. | ||
| 260 | * Update the Emm Data Structures to reflect this remapping. | ||
| 261 | * Update the Page Table too. | ||
| 262 | */ | ||
| 263 | SwapAPage(LinAdr, k) | ||
| 264 | long LinAdr; | ||
| 265 | unsigned k; | ||
| 266 | { | ||
| 267 | unsigned DosPhyPage, /* each page 16K in size, page at 256K is Page 0 */ | ||
| 268 | EmmPhyPage, /* Phy page numbering according to Emm */ | ||
| 269 | UserPFTIndex; /* index into pft386 for Emm phy page at LinAdr */ | ||
| 270 | |||
| 271 | long DMAPhyAdr, DMALinAdr; | ||
| 272 | int i, j; | ||
| 273 | |||
| 274 | /* Updating Emm data structures */ | ||
| 275 | |||
| 276 | /* Find the pft386 entry for LinAdr */ | ||
| 277 | DosPhyPage = DOSPHYPAGE(LinAdr); /* Page at 256K is page zero */ | ||
| 278 | EmmPhyPage = mappable_pages[EMM_MPindex[DosPhyPage]].physical_page; | ||
| 279 | |||
| 280 | /* get the CurRegSet entry for this physical page. */ | ||
| 281 | UserPFTIndex = GetCRSEntry(EmmPhyPage); | ||
| 282 | |||
| 283 | if (UserPFTIndex == -1) | ||
| 284 | FatalError("Cannot find PFT386 entry for EMM page corresponding to LinAdr"); | ||
| 285 | |||
| 286 | /* exchange pft386 entries at UserPFTIndex and DMA_Pages[k] */ | ||
| 287 | |||
| 288 | DMAPhyAdr = PFT(DMA_Pages[k]); | ||
| 289 | PFT(DMA_Pages[k]) = PFT(UserPFTIndex); | ||
| 290 | PFT(UserPFTIndex) = DMAPhyAdr; | ||
| 291 | |||
| 292 | /* Fix Page table entries . | ||
| 293 | * The contents of the user page and DMA buffer page are exchanged always. | ||
| 294 | * - because a mapping for this page may exist in a saved context, | ||
| 295 | * - can do a one way copy if the non-existence of such a mapping is detected | ||
| 296 | * by scanning emm_pages[]. Will optimize this later. 8/12/88 - JHB | ||
| 297 | * | ||
| 298 | * The PT entry for the user page has to be updated. | ||
| 299 | * There may or may not exist a PT entry for the DMA page. There exists | ||
| 300 | * an entry only if there exists a mapping in the CurRegSet. If there exists | ||
| 301 | * an entry it should be updated too. | ||
| 302 | */ | ||
| 303 | |||
| 304 | /* Does PT Entry exist for the DMA buffer below 1 MB? */ | ||
| 305 | |||
| 306 | for (i = 0; i < physical_page_count; i++) { | ||
| 307 | if (GetCRSEntry(i) == DMA_Pages[k]) | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | |||
| 311 | if (i == physical_page_count) { | ||
| 312 | /* No Phy page mapped to the DMA page - so no pte to be updated for DMA Page */ | ||
| 313 | Exchange16K(LinAdr, GetDMALinAdr(DMAPhyAdr)); | ||
| 314 | UpdateUserPTE(LinAdr, UserPFTIndex); | ||
| 315 | } | ||
| 316 | else { | ||
| 317 | /* ith EmmPhyPage mapped to DMA buffer | ||
| 318 | * Scan mappable_pages[] array and find the Linear address that maps to it. | ||
| 319 | */ | ||
| 320 | for (j = 0; j < MAX_PHYS_PAGES; j++) { | ||
| 321 | if (mappable_pages[j].physical_page == i) | ||
| 322 | break; | ||
| 323 | } | ||
| 324 | if (j == MAX_PHYS_PAGES) | ||
| 325 | FatalError(); /* invalid Phy page # - doesn't exist in mappable_pages[] */ | ||
| 326 | else | ||
| 327 | DMALinAdr = ((long )mappable_pages[j].page_seg) << 4; | ||
| 328 | |||
| 329 | Exchange16K(LinAdr, DMALinAdr); | ||
| 330 | ExchangePTEs(LinAdr, DMALinAdr); | ||
| 331 | } | ||
| 332 | |||
| 333 | /* UserPFTIndex is present in DMA_Pages[] we should exchange the entries in | ||
| 334 | * DMA_Pages[] */ | ||
| 335 | for (i = 0; i < DMA_PAGE_COUNT; i++) { | ||
| 336 | if (DMA_Pages[i] == UserPFTIndex) { | ||
| 337 | DMA_Pages[i] = DMA_Pages[k]; | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | /* Now, DMA_Pages[k] has a different index into the pft386[] array */ | ||
| 343 | DMA_Pages[k] = UserPFTIndex; | ||
| 344 | } | ||
| 345 | |||
| 346 | /* Update PT entry for LinAdr to map to pft386[UserPFTIndex] */ | ||
| 347 | UpdateUserPTE(LinAdr, UserPFTIndex) | ||
| 348 | long LinAdr; | ||
| 349 | unsigned UserPFTIndex; | ||
| 350 | { | ||
| 351 | unsigned index; | ||
| 352 | long pte; | ||
| 353 | |||
| 354 | index = INDEX(LinAdr); | ||
| 355 | |||
| 356 | pte = PFT(UserPFTIndex) & ~0xfff; /* Pg Frame Adr in 20 MSBs */ | ||
| 357 | |||
| 358 | SetPteFromIndex(index, pte); | ||
| 359 | SetPteFromIndex(index+1, pte+HEX4K); | ||
| 360 | SetPteFromIndex(index+2, pte+HEX4K*2); | ||
| 361 | SetPteFromIndex(index+3, pte+HEX4K*3); | ||
| 362 | } | ||
| 363 | |||
| 364 | /* exchange 4 ptes at LinAdr1 and LinAdr2 */ | ||
| 365 | ExchangePTEs(LinAdr1, LinAdr2) | ||
| 366 | long LinAdr1, LinAdr2; | ||
| 367 | { | ||
| 368 | unsigned index1, index2; | ||
| 369 | long tPte; | ||
| 370 | int i; | ||
| 371 | |||
| 372 | index1 = INDEX(LinAdr1); | ||
| 373 | index2 = INDEX(LinAdr2); | ||
| 374 | |||
| 375 | for (i = 0; i < 4; i++) { | ||
| 376 | tPte = PT(index1+i); | ||
| 377 | SetPteFromIndex(index1+i, PT(index2+i)); | ||
| 378 | SetPteFromIndex(index2+i, tPte); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | /* sanity check on the index, and then call GetPte */ | ||
| 383 | long GetPteFromIndex(index) | ||
| 384 | unsigned index; | ||
| 385 | { | ||
| 386 | unsigned i; | ||
| 387 | long PhyAdr; | ||
| 388 | |||
| 389 | PhyAdr = ((long) index) << 12; | ||
| 390 | |||
| 391 | if (PhyAdr < HEX256K || PhyAdr >= HEX1MB) | ||
| 392 | return (PhyAdr); | ||
| 393 | |||
| 394 | i = EMM_MPindex[DOSPHYPAGE(PhyAdr)]; | ||
| 395 | |||
| 396 | if (i != -1) | ||
| 397 | return GetPte(index); | ||
| 398 | else | ||
| 399 | return PhyAdr; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* sanity check on the index and then call SetPte */ | ||
| 403 | SetPteFromIndex(index, pte) | ||
| 404 | unsigned index; | ||
| 405 | long pte; | ||
| 406 | { | ||
| 407 | unsigned i; | ||
| 408 | long PhyAdr; | ||
| 409 | |||
| 410 | PhyAdr = ((long) index) << 12; | ||
| 411 | |||
| 412 | if (PhyAdr < HEX256K || PhyAdr >= HEX1MB) | ||
| 413 | return; | ||
| 414 | |||
| 415 | i = EMM_MPindex[DOSPHYPAGE(PhyAdr)]; | ||
| 416 | |||
| 417 | if (i != -1) | ||
| 418 | return SetPte(index, pte); | ||
| 419 | else | ||
| 420 | return; | ||
| 421 | } | ||
| 422 | |||
| 423 | |||
| 424 | |||
| 425 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MAPLIN.ASM b/v4.0/src/MEMM/MEMM/MAPLIN.ASM new file mode 100644 index 0000000..d37d9ac --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MAPLIN.ASM | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MapLinear - map linear address according to page tables | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MapLinear | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 2, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/08/86 Original | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/05/86 0.04 DiagByte moved to _DATA | ||
| 29 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ; | ||
| 33 | ; Functional Description: | ||
| 34 | ; This routine in this module takes a "virtual" addresses specified by | ||
| 35 | ; a virtual mode processs and "maps" it to the corresponding linear address | ||
| 36 | ; according to the linear to physical mapping in the page tables. | ||
| 37 | ; This file also contains a routine to do the inverse mapping. | ||
| 38 | ; | ||
| 39 | ; | ||
| 40 | ;****************************************************************************** | ||
| 41 | .lfcond ; list false conditionals | ||
| 42 | .386p | ||
| 43 | page | ||
| 44 | ;****************************************************************************** | ||
| 45 | ; P U B L I C D E C L A R A T I O N S | ||
| 46 | ;****************************************************************************** | ||
| 47 | ; | ||
| 48 | public MapLinear | ||
| 49 | public UnMapLinear | ||
| 50 | ; | ||
| 51 | |||
| 52 | page | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; I N C L U D E F I L E S | ||
| 55 | ;****************************************************************************** | ||
| 56 | |||
| 57 | include vdmseg.inc | ||
| 58 | include vdmsel.inc | ||
| 59 | include instr386.inc | ||
| 60 | include oemdep.inc | ||
| 61 | |||
| 62 | ;****************************************************************************** | ||
| 63 | ; E X T E R N A L R E F E R E N C E S | ||
| 64 | ;****************************************************************************** | ||
| 65 | ; | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; C O D E S E G M E N T | ||
| 68 | ;****************************************************************************** | ||
| 69 | _TEXT segment | ||
| 70 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; MapLinear - maps a linear address to it's "true" linear address. | ||
| 74 | ; | ||
| 75 | ; ENTRY: PROTECTED MODE ONLY | ||
| 76 | ; EAX = 32 bit linear address | ||
| 77 | ; | ||
| 78 | ; EXIT: EAX = 32 bit "mapped" linear address | ||
| 79 | ; | ||
| 80 | ; USED: none. | ||
| 81 | ; | ||
| 82 | ; The page dir and table set up by this routine maps the linear | ||
| 83 | ; addresses for Virtual mode programs into physical addresses using | ||
| 84 | ; the following scheme. Note that "high" memory is mapped to the | ||
| 85 | ; range starting at 16 Meg so that the page tables can be shorter. | ||
| 86 | ; | ||
| 87 | ; Linear Addr Physical Addr | ||
| 88 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 89 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 90 | ; 00110000h - 010FFFFFh 00100000h - 00FFFFFFh (top 15Meg of phys) | ||
| 91 | ifndef NOHIMEM | ||
| 92 | ; 01010000h - 0101FFFFh xxxx0000h - xxxxFFFFh ("high" memory) | ||
| 93 | ; xxxx is mapped by Map_Lin_OEM in OEMPROC module | ||
| 94 | endif | ||
| 95 | ; | ||
| 96 | ; True Linear is same as linear in our new mapping scheme. So except | ||
| 97 | ; for the "high" memory we have the true linear returned being the same | ||
| 98 | ; as linear. The new mapping is: | ||
| 99 | ; | ||
| 100 | ; Linear Addr Physical Addr | ||
| 101 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 102 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 103 | ; 00110000h - 00ffffffh 00110000h - 00ffffffh (top 15Meg of phys) | ||
| 104 | ; 01000000h - 0100FFFFh xxxx0000h - xxxxFFFFh ("high" memory) | ||
| 105 | ; xxxx is mapped by Map_Lin_OEM in OEMPROC module | ||
| 106 | ; | ||
| 107 | ;****************************************************************************** | ||
| 108 | MapLinear proc near | ||
| 109 | ; | ||
| 110 | call Map_Lin_OEM ;Q: Special mapping done by OEM routines? | ||
| 111 | jc ML_Exit ; Y: AX = mapped address | ||
| 112 | ; N: Do standard mapping | ||
| 113 | |||
| 114 | ; | ||
| 115 | ; the routine here is to be executed to get the true linear address. Since | ||
| 116 | ; it is a 1 - 1 mapping we have no code here | ||
| 117 | ; | ||
| 118 | ML_exit: | ||
| 119 | ret | ||
| 120 | ; | ||
| 121 | MapLinear endp | ||
| 122 | |||
| 123 | |||
| 124 | ;****************************************************************************** | ||
| 125 | ; UnMapLinear - maps a "true" linear address to it's linear address. | ||
| 126 | ; | ||
| 127 | ; ENTRY: EAX = 32 bit "mapped" linear address | ||
| 128 | ; | ||
| 129 | ; EXIT: EAX = 32 bit linear address | ||
| 130 | ; | ||
| 131 | ; USED: none. | ||
| 132 | ; | ||
| 133 | ; The page dir and table set up maps the linear | ||
| 134 | ; addresses for Virtual mode programs into physical addresses using | ||
| 135 | ; the following scheme. | ||
| 136 | ; Linear Addr Physical Addr | ||
| 137 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 138 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 139 | ; 00110000h - 010FFFFFh 00100000h - 00FFFFFFh (top 15Meg of phys) | ||
| 140 | ifndef NOHIMEM | ||
| 141 | ; 01010000h - 0101FFFFh xxxx0000h - xxxxFFFFh (high memory) | ||
| 142 | ; xxxx is mapped by UMap_Lin_OEM in OEMPROC module | ||
| 143 | endif | ||
| 144 | ; | ||
| 145 | ; Our new mapping scheme is: | ||
| 146 | ; | ||
| 147 | ; Linear Addr Physical Addr | ||
| 148 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 149 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 150 | ; 00110000h - 00ffffffh 00110000h - 00ffffffh (top 15Meg of phys) | ||
| 151 | ; 01000000h - 0100FFFFh xxxx0000h - xxxxFFFFh ("high" memory) | ||
| 152 | ; xxxx is mapped by Map_Lin_OEM in OEMPROC module | ||
| 153 | ; | ||
| 154 | ;****************************************************************************** | ||
| 155 | UnMapLinear proc near | ||
| 156 | ; | ||
| 157 | cmp eax,01000000 ; | ||
| 158 | jb UML_mask ; N: chk for < 1 meg | ||
| 159 | call UMap_Lin_OEM ; Y: set EAX to physical address for diags | ||
| 160 | jmp short UML_exit | ||
| 161 | |||
| 162 | UML_mask: | ||
| 163 | UML_exit: | ||
| 164 | ret | ||
| 165 | ; | ||
| 166 | UnMapLinear endp | ||
| 167 | |||
| 168 | |||
| 169 | _TEXT ends | ||
| 170 | |||
| 171 | end | ||
| 172 | |||
diff --git a/v4.0/src/MEMM/MEMM/MEMM386.ASM b/v4.0/src/MEMM/MEMM/MEMM386.ASM new file mode 100644 index 0000000..d2b6d26 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMM386.ASM | |||
| @@ -0,0 +1,561 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMM386 - main module for MEMM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MEMM386 - main module | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: May 24,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 04/24/86 Original From EMML LIM driver. | ||
| 27 | ; 06/26/86 0.02 Put CLD in Inst_Chk | ||
| 28 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM. | ||
| 29 | ; 07/05/86 0.04 Changed segment to R_CODE | ||
| 30 | ; 06/07/88 exclude VDISK header info's since we are | ||
| 31 | ; using INT-15 method now (Paul Chan) | ||
| 32 | ; 06/21/88 Removed VDISK stuff. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | ; Functional Description: | ||
| 36 | ; MEMM is an Expanded Memory Manager which implements expanded memory | ||
| 37 | ; on the MICROSOFT 386 machine. MEMM uses Virtual mode and paging on | ||
| 38 | ; the 386 to make Extended memory useable as expanded memory. The are two | ||
| 39 | ; basic functional parts of MEMM; the Virtual DOS Monitor (VDM) and the | ||
| 40 | ; Expanded Memory Manager (EMM). VDM simulates the 386 Real mode under the | ||
| 41 | ; 386 Virtual mode. EMM provides the software functionality for a EMM as | ||
| 42 | ; described in the Lotus-Intel-Microsoft (LIM) specification for expanded | ||
| 43 | ; memory. | ||
| 44 | ; This module contains the Device Driver header, stategy, and interrupt | ||
| 45 | ; routines required by a LIM standard EMM. | ||
| 46 | ; This device driver is a .EXE file and may be invoked as a DOS utility | ||
| 47 | ; program as well as loaded as a device driver. When it is loaded as a | ||
| 48 | ; DOS utility, MEMM has three command line options: ON,OFF and AUTO. | ||
| 49 | ; The OFF options disables MEMM and exits to MS-DOS in real mode. | ||
| 50 | ; The ON option enables MEMM and exits to MS-DOS in virtual mode (only | ||
| 51 | ; if the MEMM.EXE driver has been loaded). The AUTO option puts | ||
| 52 | ; MEMM in "auto mode". In this mode, MEMM will enable and disable | ||
| 53 | ; itself automatically, depending on accesses to the EMM functions. | ||
| 54 | ; The general device driver CONFIG.SYS options are described below. | ||
| 55 | ; | ||
| 56 | ; Syntax: | ||
| 57 | ; | ||
| 58 | ; device=[d]:[<path>]MEMM.EXE [SIZE] [Mx] [ON | OFF | AUTO] | ||
| 59 | ; | ||
| 60 | ; | ||
| 61 | ; NOTE: SUNILP - See if we need the /X option for excluding segments from | ||
| 62 | ; being mappable. This turned out to be quite useful in ps2emm and since | ||
| 63 | ; here we are dealing with different hardware this option may turn out | ||
| 64 | ; essential here**** WISH001 | ||
| 65 | ; | ||
| 66 | ; The following sections describe the optional arguments which the | ||
| 67 | ; user may specify for MEMM.EXE at load time (in the CONFIG.SYS | ||
| 68 | ; file). These arguments are placed after the device driver name | ||
| 69 | ; in the CONFIG.SYS file. | ||
| 70 | ; | ||
| 71 | ; MEMM arguments in the CONFIG.SYS file must be separated by spaces | ||
| 72 | ; or tabs. Arguments may appear in any order; however, any redundant | ||
| 73 | ; or excessive instances are ignored and only the first valid instance | ||
| 74 | ; of an argument is used. Invalid or extraneous arguments produce an | ||
| 75 | ; error message. | ||
| 76 | ; | ||
| 77 | ; [SIZE] | ||
| 78 | ; | ||
| 79 | ; The argument SIZE is the amount of expanded memory desired in | ||
| 80 | ; K bytes. The default amount of expanded memory, 256K, is available | ||
| 81 | ; without using any extended memory. To use more than 256K of | ||
| 82 | ; expanded memory, the 386 system must have extended memory. When | ||
| 83 | ; If there is not enough memory available | ||
| 84 | ; to provide SIZE kbytes of expanded memory, MEMM will adjust SIZE to | ||
| 85 | ; provide as much expanded memory as possible. | ||
| 86 | ; | ||
| 87 | ; - The valid range for SIZE is 16K - 8192K. Value outside this range | ||
| 88 | ; are converted to the default of 256K. | ||
| 89 | ; | ||
| 90 | ; - If SIZE is not a multiple of 16K (size of an EMM page), then SIZE | ||
| 91 | ; is rounded down to the nearest multiple of 16K. | ||
| 92 | ; | ||
| 93 | ; [Mx] | ||
| 94 | ; | ||
| 95 | ; The argument [Mx] specifies the address of the 64k EMM page frame. | ||
| 96 | ; This argument is optional since MEMM can choose an appropriate | ||
| 97 | ; location for the page frame when it is loaded. To choose a location | ||
| 98 | ; the 386 EMM driver scans memory addresses above video memory for | ||
| 99 | ; an appropriate 64K address range for the EMM page frame. For a | ||
| 100 | ; default page frame base address MEMM looks for option ROMs and | ||
| 101 | ; RAM in the EMM addressing range and chooses a 64K slot of memory | ||
| 102 | ; for the page frame which apparently does not confict with existing | ||
| 103 | ; memory. The user may override the 386 EMM driver's choice by | ||
| 104 | ; specifying the beginning address with the Mx argument. If the | ||
| 105 | ; user specifies a page frame base address which conflicts with an | ||
| 106 | ; option ROM or RAM, MEMM displays a warning message and uses the | ||
| 107 | ; specified page frame base address. | ||
| 108 | ; | ||
| 109 | ; The following options are possible: | ||
| 110 | ; Page Frame Base Address | ||
| 111 | ; M1 => 0C0000 Hex | ||
| 112 | ; M2 => 0C4000 Hex | ||
| 113 | ; M3 => 0C8000 Hex | ||
| 114 | ; M4 => 0CC000 Hex | ||
| 115 | ; M5 => 0D0000 Hex | ||
| 116 | ; | ||
| 117 | ; [ ON | OFF | AUTO ] | ||
| 118 | ; | ||
| 119 | ; The argument [ON | OFF | AUTO] specifies the state of the 386 when | ||
| 120 | ; MEMM returns to DOS after the driver INIT routine finishes. If this | ||
| 121 | ; argument is ON, then MEMM returns to DOS in virtual mode and | ||
| 122 | ; expanded memory is available. If this argument is OFF, then MEMM | ||
| 123 | ; returns to DOS in real mode and expanded memory is not available | ||
| 124 | ; until MEMM is turned ON. The default for this argument is AUTO | ||
| 125 | ; mode. In AUTO mode, the MEMM.EXE device driver will exit to | ||
| 126 | ; DOS in the OFF state; afterwards, MEMM will enable and disable | ||
| 127 | ; itself automatically. In the AUTO mode, MEMM will be enabled | ||
| 128 | ; only while the expanded memory manager is in use. | ||
| 129 | ; | ||
| 130 | ; | ||
| 131 | ;****************************************************************************** | ||
| 132 | .lfcond | ||
| 133 | .386p | ||
| 134 | page | ||
| 135 | ;****************************************************************************** | ||
| 136 | ; P U B L I C D E C L A R A T I O N S | ||
| 137 | ;****************************************************************************** | ||
| 138 | |||
| 139 | ; | ||
| 140 | ; R_CODE publics | ||
| 141 | ; | ||
| 142 | public strategy | ||
| 143 | public interrupt | ||
| 144 | public MEMM_Entry | ||
| 145 | |||
| 146 | ; | ||
| 147 | ; _TEXT publics | ||
| 148 | ; | ||
| 149 | public ELIM_EXE ; .EXE execution entry point | ||
| 150 | public ELIM_link | ||
| 151 | public Inst_chk ; Check to see if MEMM already installed | ||
| 152 | public Inst_chk_f ; Far call version of above | ||
| 153 | |||
| 154 | page | ||
| 155 | ;****************************************************************************** | ||
| 156 | ; L O C A L C O N S T A N T S | ||
| 157 | ;****************************************************************************** | ||
| 158 | ; | ||
| 159 | include driver.equ | ||
| 160 | include driver.str | ||
| 161 | include vdmseg.inc | ||
| 162 | |||
| 163 | FALSE equ 0 | ||
| 164 | TRUE equ not FALSE | ||
| 165 | |||
| 166 | MS_DOS equ 21h ; DOS interrupt | ||
| 167 | GET_PSP equ 62h ; get program segment prefix | ||
| 168 | |||
| 169 | NULL EQU 0FFFFH ;Null address pointer | ||
| 170 | |||
| 171 | dospsp_str struc | ||
| 172 | db 80h dup (?) | ||
| 173 | cmd_len db ? ; length of command line | ||
| 174 | cmd_line db ? ; commande line | ||
| 175 | dospsp_str ends | ||
| 176 | |||
| 177 | ;****************************************************************************** | ||
| 178 | ; E X T E R N A L R E F E R E N C E S | ||
| 179 | ;****************************************************************************** | ||
| 180 | ; | ||
| 181 | abs0 segment use16 at 0000h | ||
| 182 | |||
| 183 | org 67h*4 ; EMM function interrupt | ||
| 184 | int67 dw ? ; offset of vector | ||
| 185 | dw ? ; segment of vector | ||
| 186 | abs0 ends | ||
| 187 | |||
| 188 | LAST segment | ||
| 189 | extrn Init_MEMM386:far ; initializes VDM,EMM, and driver | ||
| 190 | LAST ends | ||
| 191 | |||
| 192 | R_CODE segment | ||
| 193 | extrn ELIM_Entry:far ; general entry point for MEMM functions | ||
| 194 | R_CODE ends | ||
| 195 | |||
| 196 | _TEXT segment | ||
| 197 | extrn onf_func:near ; perform on, off, or auto checking for elim.exe | ||
| 198 | _TEXT ends | ||
| 199 | |||
| 200 | page | ||
| 201 | ;****************************************************************************** | ||
| 202 | ; S E G M E N T D E F I N I T I O N | ||
| 203 | ;****************************************************************************** | ||
| 204 | ; | ||
| 205 | ;****************************************************************************** | ||
| 206 | ; | ||
| 207 | ; R_CODE Code Segment | ||
| 208 | ; | ||
| 209 | ;****************************************************************************** | ||
| 210 | ; | ||
| 211 | R_CODE segment | ||
| 212 | assume cs:R_CODE, ds:R_CODE, es:R_CODE, ss:R_CODE | ||
| 213 | |||
| 214 | Start: | ||
| 215 | ;****************************************************************************** | ||
| 216 | ; Device driver header | ||
| 217 | ;****************************************************************************** | ||
| 218 | ; | ||
| 219 | DW NULL ;Null segment address | ||
| 220 | DW NULL ;Null offset address | ||
| 221 | DW CHAR_DEV+IOCTL_SUP ;Attribute - Char | ||
| 222 | DW OFFSET STRATEGY ;Strategy routine entry | ||
| 223 | DW OFFSET INTERRUPT ;Interrupt routine entry | ||
| 224 | DB 'EMMXXXX0' ;Character device name | ||
| 225 | ; | ||
| 226 | ;****************************************************************************** | ||
| 227 | ; GENERAL FUNCTIONS ENTRY POINT | ||
| 228 | ; R_CODE:ELIM_Entry is a entry point for executing general MEMM | ||
| 229 | ; functions. (e.g. ON, OFF function). | ||
| 230 | ;****************************************************************************** | ||
| 231 | ; | ||
| 232 | MEMM_Entry dw offset ELIM_Entry ; general entry point | ||
| 233 | |||
| 234 | ;****************************************************************************** | ||
| 235 | ; MEMM signature | ||
| 236 | ;****************************************************************************** | ||
| 237 | memmsig db 'MICROSOFT EXPANDED MEMORY MANAGER 386' | ||
| 238 | SIG_LENGTH equ (this byte - memmsig) | ||
| 239 | |||
| 240 | page | ||
| 241 | ;****************************************************************************** | ||
| 242 | ; L O C A L D A T A A R E A | ||
| 243 | ;****************************************************************************** | ||
| 244 | |||
| 245 | ; | ||
| 246 | ; Define the command dispatch table for the driver functions | ||
| 247 | ; | ||
| 248 | Cmd_Table LABEL NEAR | ||
| 249 | DW Init_Call ;0 - Initialization | ||
| 250 | DW Null_Exit ;1 - Media Check | ||
| 251 | DW Null_Exit ;2 - Get BPB | ||
| 252 | DW Null_Exit ;3 - IOCTL input | ||
| 253 | DW Null_Exit ;4 - Input (Destructive) | ||
| 254 | DW Null_Exit ;5 - No wait input | ||
| 255 | DW Null_Exit ;6 - Input status | ||
| 256 | DW Null_Exit ;7 - Input buffer flush | ||
| 257 | DW Null_Exit ;8 - Output (Write) | ||
| 258 | DW Null_Exit ;9 - Output with verify | ||
| 259 | DW Null_Exit ;A - Output status | ||
| 260 | DW Null_Exit ;B - Output buffer flush | ||
| 261 | DW Null_Exit ;C - IOCTL output | ||
| 262 | TBL_LENGTH EQU (THIS BYTE-CMD_TABLE)/2 ;Dispatch table length | ||
| 263 | |||
| 264 | public ReqPtr | ||
| 265 | ReqPtr label dword ; dword ptr to Request Header | ||
| 266 | ReqOff dw 0 ; saved offset of Request Header | ||
| 267 | ReqSeg dw 0 ; saved segment of Request Header | ||
| 268 | |||
| 269 | page | ||
| 270 | ;****************************************************************************** | ||
| 271 | ; Strategy - strategy routine for MEMM | ||
| 272 | ; | ||
| 273 | ; ENTRY: ES:BX = pointer to Request Header | ||
| 274 | ; | ||
| 275 | ; EXIT: CS:ReqOff, CS:ReqSeg - saved pointer to Request Header | ||
| 276 | ; | ||
| 277 | ; USED: none | ||
| 278 | ; | ||
| 279 | ;****************************************************************************** | ||
| 280 | Strategy proc far | ||
| 281 | mov CS:[ReqOff],bx ;Save header offset | ||
| 282 | mov CS:[ReqSeg],es ;Save header segment | ||
| 283 | ret | ||
| 284 | Strategy endp | ||
| 285 | |||
| 286 | ;****************************************************************************** | ||
| 287 | ; Interrupt - device driver interrupt routine for MEMM | ||
| 288 | ; | ||
| 289 | ; ENTRY: CS:ReqPtr = pointer to request header. | ||
| 290 | ; | ||
| 291 | ; EXIT: Request completed. | ||
| 292 | ; | ||
| 293 | ; USED: none | ||
| 294 | ; | ||
| 295 | ;****************************************************************************** | ||
| 296 | Interrupt proc far | ||
| 297 | push ax | ||
| 298 | push bx | ||
| 299 | push cx | ||
| 300 | push dx | ||
| 301 | push si | ||
| 302 | push di | ||
| 303 | push ds | ||
| 304 | push es | ||
| 305 | cld ;All strings forward | ||
| 306 | lds bx,CS:[ReqPtr] ;DS:BX pts to Request Header | ||
| 307 | mov al,[bx.COMMAND_CODE] ;Get the command code | ||
| 308 | cmp al,TBL_LENGTH ;Check for validity | ||
| 309 | jae Invalid ;Jump if command invalid | ||
| 310 | cbw ;Command to a full word | ||
| 311 | shl ax,1 ;Compute dispatch index | ||
| 312 | mov si,OFFSET Cmd_Table ;Point to dispatch table | ||
| 313 | add si,ax ;Index based on command | ||
| 314 | call CS:[si] ;Call correct routine | ||
| 315 | |||
| 316 | ; | ||
| 317 | ; ENTRY: AX = Status field for Request Header | ||
| 318 | ; | ||
| 319 | Finish: | ||
| 320 | lds bx,CS:[ReqPtr] ;Get request header ptr. | ||
| 321 | or ah,DON ;Set done bit in status | ||
| 322 | mov DS:[bx.STATUS_WORD],ax ;Save status in header | ||
| 323 | pop es ;Restore the ES register | ||
| 324 | pop ds | ||
| 325 | pop di | ||
| 326 | pop si | ||
| 327 | pop dx | ||
| 328 | pop cx | ||
| 329 | pop bx | ||
| 330 | pop ax | ||
| 331 | ret | ||
| 332 | Invalid: | ||
| 333 | mov al,UNK_COMMAND ; unknown command | ||
| 334 | mov ah,ERR ; error | ||
| 335 | stc | ||
| 336 | jmp SHORT Finish ;Go return to caller | ||
| 337 | Interrupt endp | ||
| 338 | |||
| 339 | ;****************************************************************************** | ||
| 340 | ; Null_Exit: do nothing | ||
| 341 | ; | ||
| 342 | ; ENTRY: DS:BX pts to request header | ||
| 343 | ; | ||
| 344 | ; EXIT: No error returned. | ||
| 345 | ; CLC | ||
| 346 | ; | ||
| 347 | ;****************************************************************************** | ||
| 348 | Null_Exit proc near | ||
| 349 | ; | ||
| 350 | xor ax,ax | ||
| 351 | clc | ||
| 352 | ret | ||
| 353 | ; | ||
| 354 | Null_Exit endp | ||
| 355 | |||
| 356 | ;****************************************************************************** | ||
| 357 | ; Init_Call - call initialization routine | ||
| 358 | ; | ||
| 359 | ; ENTRY: DS:BX pts to request header | ||
| 360 | ; | ||
| 361 | ; EXIT: AX = status field for request header | ||
| 362 | ; | ||
| 363 | ;****************************************************************************** | ||
| 364 | Init_Call proc near | ||
| 365 | ; | ||
| 366 | call Init_MEMM386 | ||
| 367 | ret | ||
| 368 | ; | ||
| 369 | Init_Call endp | ||
| 370 | |||
| 371 | ;****************************************************************************** | ||
| 372 | db 'SBP' | ||
| 373 | db 'BMT' | ||
| 374 | ;****************************************************************************** | ||
| 375 | ; | ||
| 376 | |||
| 377 | R_CODE ends | ||
| 378 | |||
| 379 | page | ||
| 380 | ;****************************************************************************** | ||
| 381 | ; | ||
| 382 | ; _TEXT Code Segment | ||
| 383 | ; | ||
| 384 | ;****************************************************************************** | ||
| 385 | _TEXT segment | ||
| 386 | assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT | ||
| 387 | |||
| 388 | FarLink dd 0 ; far pointer to installed memm386 entry point | ||
| 389 | ; OK as writeable because it is only used | ||
| 390 | ; during .EXE execution. | ||
| 391 | |||
| 392 | ; | ||
| 393 | rh db 23,0,0,0,0,8 dup (0) | ||
| 394 | db 10 dup (0) | ||
| 395 | ; | ||
| 396 | MEMM: | ||
| 397 | ;****************************************************************************** | ||
| 398 | ; | ||
| 399 | ; ELIM_EXE - .EXE entry point - when MEMM.EXE is invoked as a DOS | ||
| 400 | ; utility. | ||
| 401 | ; | ||
| 402 | ;****************************************************************************** | ||
| 403 | |||
| 404 | ;------------------------------------------------------------------------------ | ||
| 405 | ; NOTE** SUNILP .. Paulch changed this to load it as an terminate and stay | ||
| 406 | ; resident. This entry should only be to turn an existing MEMM ON | ||
| 407 | ; OFF or AUTO. Once the driver is debugged change this back to the | ||
| 408 | ; original code given here in comments. Also remove the above rh | ||
| 409 | ; storage block. WISH002 | ||
| 410 | ;ELIM_EXE proc near | ||
| 411 | ;; | ||
| 412 | ; push cs | ||
| 413 | ; pop ds ; ds = cs | ||
| 414 | ; mov ah,GET_PSP ; get segment of PSP | ||
| 415 | ; int MS_DOS | ||
| 416 | ; mov es,bx ; DOS call returned seg in bx | ||
| 417 | ; mov di,offset cmd_line ; es:di = command line | ||
| 418 | ; call onf_func ; look for on, off, or auto | ||
| 419 | ; mov ax,4c00h ; exit to DOS | ||
| 420 | ; int MS_DOS | ||
| 421 | ;; | ||
| 422 | ;ELIM_EXE endp | ||
| 423 | ;; | ||
| 424 | ;------------------------------------------------------------------------------ | ||
| 425 | |||
| 426 | ELIM_EXE proc near | ||
| 427 | ; | ||
| 428 | extrn exe_stack:byte | ||
| 429 | |||
| 430 | push seg STACK | ||
| 431 | pop ss | ||
| 432 | mov sp, offset STACK:exe_stack | ||
| 433 | push cs | ||
| 434 | pop ds | ||
| 435 | mov ah,GET_PSP | ||
| 436 | int MS_DOS | ||
| 437 | mov es,bx | ||
| 438 | mov di,offset cmd_line | ||
| 439 | |||
| 440 | mov bx,seg rh | ||
| 441 | mov ds,bx | ||
| 442 | mov bx,offset rh | ||
| 443 | mov [bx+20],es | ||
| 444 | mov [bx+18],di | ||
| 445 | |||
| 446 | push ds | ||
| 447 | pop es | ||
| 448 | call Strategy | ||
| 449 | call Interrupt | ||
| 450 | |||
| 451 | mov bx,seg rh | ||
| 452 | mov es,bx | ||
| 453 | mov bx,offset rh | ||
| 454 | mov dx,es:[bx+16] | ||
| 455 | sub dx,es:[bx+20] | ||
| 456 | mov ah,31h | ||
| 457 | int 21h | ||
| 458 | ; | ||
| 459 | |||
| 460 | ; push cs | ||
| 461 | ; pop ds ; ds = cs | ||
| 462 | ; mov ah,GET_PSP ; get segment of PSP | ||
| 463 | ; int MS_DOS | ||
| 464 | ; mov es,bx ; DOS call returned seg in bx | ||
| 465 | ; mov di,offset cmd_line ; es:di = command line | ||
| 466 | ; call onf_func ; look for on, off, or auto | ||
| 467 | mov ax,4c00h ; exit to DOS | ||
| 468 | int MS_DOS | ||
| 469 | ; | ||
| 470 | ELIM_EXE endp | ||
| 471 | ; | ||
| 472 | ;****************************************************************************** | ||
| 473 | ; Inst_chk_f - call Inst_chk | ||
| 474 | ; | ||
| 475 | ; ENTRY: see Inst_chk | ||
| 476 | ; | ||
| 477 | ; EXIT: see Inst_chk | ||
| 478 | ; | ||
| 479 | ; USED: none | ||
| 480 | ; | ||
| 481 | ;****************************************************************************** | ||
| 482 | Inst_chk_f proc far | ||
| 483 | call Inst_chk | ||
| 484 | ret | ||
| 485 | Inst_chk_f endp | ||
| 486 | |||
| 487 | ;****************************************************************************** | ||
| 488 | ; Inst_chk - Check to see if MEMM is already installed | ||
| 489 | ; | ||
| 490 | ; ENTRY: int 67 vector | ||
| 491 | ; | ||
| 492 | ; EXIT: ax = 0 if not already installed | ||
| 493 | ; ax = 1 if MEMM is already installed | ||
| 494 | ; _TEXT:[FarLink] = far address for installed MEMM entry point | ||
| 495 | ; | ||
| 496 | ; USED: none | ||
| 497 | ; | ||
| 498 | ;****************************************************************************** | ||
| 499 | Inst_chk proc near | ||
| 500 | push di ; save di | ||
| 501 | push si ; and si | ||
| 502 | push ds ; and ds | ||
| 503 | push es ; and es | ||
| 504 | push cx ; and cx | ||
| 505 | ; | ||
| 506 | xor ax,ax ; put segment 0000h in ds | ||
| 507 | mov ds,ax | ||
| 508 | ASSUME DS:abs0 ; assume ds is abs0 | ||
| 509 | mov ax,[int67+2] ; get segment pointed to by int 67 | ||
| 510 | mov es,ax | ||
| 511 | ASSUME ES:R_CODE | ||
| 512 | |||
| 513 | push seg R_CODE | ||
| 514 | pop ds ; set DS = R_CODE | ||
| 515 | assume DS:R_CODE ; update assume | ||
| 516 | |||
| 517 | mov di,offset memmsig ; memm386 signature | ||
| 518 | mov si,di ; save for source string | ||
| 519 | xor ax,ax ; initialize to not found | ||
| 520 | mov cx,SIG_LENGTH ; length to compare | ||
| 521 | cld ; strings foward | ||
| 522 | repe cmpsb ; q: is the memm386 signature out there? | ||
| 523 | jne not_inst ; n: return zero | ||
| 524 | inc ax ; y: return one | ||
| 525 | mov word ptr CS:[FarLink+2],es ; set segment of far call | ||
| 526 | mov cx,ES:[MEMM_Entry] ; get offset for far call | ||
| 527 | mov word ptr CS:[FarLink],cx ; set offset of far call | ||
| 528 | not_inst: | ||
| 529 | |||
| 530 | ASSUME DS:_TEXT, ES:_TEXT | ||
| 531 | |||
| 532 | pop cx | ||
| 533 | pop es | ||
| 534 | pop ds | ||
| 535 | pop si | ||
| 536 | pop di | ||
| 537 | ret | ||
| 538 | Inst_chk endp | ||
| 539 | |||
| 540 | ;****************************************************************************** | ||
| 541 | ; ELIM_link - Link to Installed MEMM's ELIM_Entry | ||
| 542 | ; | ||
| 543 | ; ENTRY: see ELIM_Entry | ||
| 544 | ; and | ||
| 545 | ; _TEXT:[FarLink] = far address of installed MEMM ELIM_Entry | ||
| 546 | ; | ||
| 547 | ; EXIT: see ELIM_Entry | ||
| 548 | ; | ||
| 549 | ; USED: none | ||
| 550 | ; | ||
| 551 | ;****************************************************************************** | ||
| 552 | ELIM_link proc near | ||
| 553 | call CS:[FarLink] | ||
| 554 | ret | ||
| 555 | ELIM_link endp | ||
| 556 | |||
| 557 | |||
| 558 | _TEXT ends | ||
| 559 | |||
| 560 | end MEMM | ||
| 561 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMMCOM.ASM b/v4.0/src/MEMM/MEMM/MEMMCOM.ASM new file mode 100644 index 0000000..b92cfdb --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMMCOM.ASM | |||
| @@ -0,0 +1,243 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMMCOM - main module for MEMM.COM | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.COM - MICROSOFT Expanded Memory Manager 386 Utility | ||
| 11 | ; | ||
| 12 | ; Module: MEMMCOM - main module for MEMM.COM | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: June 4, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/21/86 0.02 Added CLD to Inst_Chk | ||
| 28 | ; 06/28/86 0.02 Name change from MEMM386.COM to MEMM.COM | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ; | ||
| 32 | ; Functional Description: | ||
| 33 | ; MEMM.COM which allows the user to poll or set the operating mode | ||
| 34 | ; of the MEMM device driver. | ||
| 35 | ; Syntax: | ||
| 36 | ; MEMM [ ON | OFF | AUTO ] | ||
| 37 | ; | ||
| 38 | ; If the user specifies no arguments, MEMM.COM will return the | ||
| 39 | ; current mode of the MEMM device driver. | ||
| 40 | ; | ||
| 41 | ; ON | ||
| 42 | ; If the user specifies ON, MEMM.COM enables the MEMM driver; | ||
| 43 | ; expanded memory is available and the processor is in virtual mode. | ||
| 44 | ; | ||
| 45 | ; OFF | ||
| 46 | ; If the user specifies OFF, MEMM.COM disables the MEMM driver; | ||
| 47 | ; expanded memory is not available and the processor is in real mode. | ||
| 48 | ; | ||
| 49 | ; AUTO | ||
| 50 | ; If the user specifies AUTO, MEMM.COM enables the MEMM driver's auto | ||
| 51 | ; mode. In auto mode, the driver will enable and disable itself | ||
| 52 | ; "automatically" (depending on accesses to the EMM functions). | ||
| 53 | ; | ||
| 54 | ;****************************************************************************** | ||
| 55 | .lfcond ; list false conditionals | ||
| 56 | .386p | ||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; P U B L I C D E C L A R A T I O N S | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; | ||
| 62 | public EMM386 | ||
| 63 | public Inst_chk | ||
| 64 | public ELIM_link | ||
| 65 | ; | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; E X T E R N A L R E F E R E N C E S | ||
| 68 | ;****************************************************************************** | ||
| 69 | _TEXT segment byte use16 public 'CODE' | ||
| 70 | extrn onf_func:near | ||
| 71 | _TEXT ends | ||
| 72 | abs0 segment use16 at 0000h | ||
| 73 | |||
| 74 | org 67h*4 ; EMM function interrupt | ||
| 75 | int67 dw ? ; offset of vector | ||
| 76 | dw ? ; segment of vector | ||
| 77 | abs0 ends | ||
| 78 | |||
| 79 | |||
| 80 | page | ||
| 81 | ;****************************************************************************** | ||
| 82 | ; L O C A L C O N S T A N T S | ||
| 83 | ;****************************************************************************** | ||
| 84 | ; | ||
| 85 | |||
| 86 | MSDOS equ 21h ; MS-DOS function call | ||
| 87 | |||
| 88 | ; | ||
| 89 | ; Device driver header for MEMM | ||
| 90 | ; | ||
| 91 | emm_hdr STRUC | ||
| 92 | ; | ||
| 93 | DW ? ;Null segment address | ||
| 94 | DW ? ;Null offset address | ||
| 95 | DW ? ;Attribute - Char | ||
| 96 | DW ? ;Strategy routine entry | ||
| 97 | DW ? ;Interrupt routine entry | ||
| 98 | DB 'EMMXXXX0' ;Character device name | ||
| 99 | ; | ||
| 100 | ; GENERAL FUNCTIONS ENTRY POINT | ||
| 101 | ; ELIM_Entry is a entry point for executing general MEMM | ||
| 102 | ; functions. (e.g. ON, OFF function). | ||
| 103 | ; | ||
| 104 | ELIM_Entry_off dw ? ; general entry point | ||
| 105 | |||
| 106 | ; | ||
| 107 | ; MEMM signature | ||
| 108 | ; | ||
| 109 | memmsig db ? ; MEMM signature | ||
| 110 | |||
| 111 | emm_hdr ends | ||
| 112 | |||
| 113 | ;****************************************************************************** | ||
| 114 | ; S E G M E N T D E F I N I T I O N | ||
| 115 | ;****************************************************************************** | ||
| 116 | ; | ||
| 117 | _TEXT segment byte use16 public 'CODE' | ||
| 118 | assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT | ||
| 119 | org 81h | ||
| 120 | cmd_line dw ? ; pointer to command line | ||
| 121 | ; | ||
| 122 | ;****************************************************************************** | ||
| 123 | ; M O D U L E E N T R Y P O I N T | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; | ||
| 126 | ; Standard .COM entry conditions are assumed | ||
| 127 | ; | ||
| 128 | org 100h | ||
| 129 | EMM386 proc near | ||
| 130 | jmp start | ||
| 131 | ;****************************************************************************** | ||
| 132 | ; L O C A L D A T A A R E A | ||
| 133 | ;****************************************************************************** | ||
| 134 | ; | ||
| 135 | |||
| 136 | oursig db 'MICROSOFT EXPANDED MEMORY MANAGER 386' | ||
| 137 | SIG_LENGTH equ (this byte - oursig) | ||
| 138 | ; | ||
| 139 | ; define double word to store segment/offset of status routine for far call | ||
| 140 | ; | ||
| 141 | status_loc label dword | ||
| 142 | entry_off dw 0 ; store offset for far call | ||
| 143 | entry_seg dw 0 ; store segment for far call | ||
| 144 | ; | ||
| 145 | |||
| 146 | start: | ||
| 147 | push cs | ||
| 148 | pop ds | ||
| 149 | push cs | ||
| 150 | pop es | ||
| 151 | |||
| 152 | ; | ||
| 153 | cli | ||
| 154 | mov sp,offset Stack_Top | ||
| 155 | sti | ||
| 156 | ; | ||
| 157 | cld | ||
| 158 | ; | ||
| 159 | mov di,offset cmd_line ; es:di = command line pointer | ||
| 160 | call onf_func ; do the on/off function | ||
| 161 | |||
| 162 | mov ax,4C00h | ||
| 163 | int MSDOS ; exit to DOS | ||
| 164 | |||
| 165 | EMM386 endp | ||
| 166 | |||
| 167 | page | ||
| 168 | ;****************************************************************************** | ||
| 169 | ; ELIM_link - Call ELIM_Entry status routine via the status_loc | ||
| 170 | ; | ||
| 171 | ; ENTRY: [status_loc] contains the far address | ||
| 172 | ; | ||
| 173 | ; EXIT: ? | ||
| 174 | ; | ||
| 175 | ; USED: none | ||
| 176 | ; | ||
| 177 | ;****************************************************************************** | ||
| 178 | ELIM_link proc near | ||
| 179 | call status_loc | ||
| 180 | ret | ||
| 181 | ELIM_link endp | ||
| 182 | page | ||
| 183 | ;****************************************************************************** | ||
| 184 | ; Inst_chk - Check to see if MEMM is already installed | ||
| 185 | ; | ||
| 186 | ; ENTRY: int 67 vector | ||
| 187 | ; | ||
| 188 | ; EXIT: ax = 0 if not already installed | ||
| 189 | ; ax = 1 if MEMM is already installed | ||
| 190 | ; If MEMM is installed, then | ||
| 191 | ; [entry_seg] = segment of driver header | ||
| 192 | ; [entry_off] = offset of status routine in MEMM | ||
| 193 | ; | ||
| 194 | ; USED: none | ||
| 195 | ; | ||
| 196 | ;****************************************************************************** | ||
| 197 | Inst_chk proc near | ||
| 198 | push di ; save di | ||
| 199 | push si ; and si | ||
| 200 | push ds ; and ds | ||
| 201 | push es ; and es | ||
| 202 | push cx ; and cx | ||
| 203 | ; | ||
| 204 | xor ax,ax ; put segment 0000h in ds | ||
| 205 | mov ds,ax | ||
| 206 | assume ds:abs0 ; assume ds is abs0 | ||
| 207 | mov ax,[int67+2] ; get segment pointed to by int 67 | ||
| 208 | mov es,ax | ||
| 209 | |||
| 210 | assume ds:_TEXT ; update assume | ||
| 211 | push cs | ||
| 212 | pop ds ; set DS = _TEXT | ||
| 213 | |||
| 214 | mov di,offset memmsig ; MEMM signature | ||
| 215 | mov si,offset oursig ; point to our signature | ||
| 216 | xor ax,ax ; initialize to not found | ||
| 217 | mov cx,SIG_LENGTH ; length to compare | ||
| 218 | cld ; strings foward | ||
| 219 | repe cmpsb ; q: is the MEMM signature out there? | ||
| 220 | jne not_inst ; n: return zero | ||
| 221 | inc ax ; y: return one | ||
| 222 | mov [entry_seg],es ; save segment for far call | ||
| 223 | xor di,di | ||
| 224 | mov cx,es:[ELIM_Entry_off] ; save offset for far call | ||
| 225 | mov [entry_off],cx | ||
| 226 | not_inst: | ||
| 227 | pop cx | ||
| 228 | pop es | ||
| 229 | pop ds | ||
| 230 | pop si | ||
| 231 | pop di | ||
| 232 | ret | ||
| 233 | Inst_chk endp | ||
| 234 | |||
| 235 | |||
| 236 | db 100h dup (0) | ||
| 237 | Stack_Top: | ||
| 238 | db 0 | ||
| 239 | |||
| 240 | _TEXT ends | ||
| 241 | |||
| 242 | end EMM386 | ||
| 243 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMMINC.ASM b/v4.0/src/MEMM/MEMM/MEMMINC.ASM new file mode 100644 index 0000000..1eb897f --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMMINC.ASM | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMMINC.ASM - lists all MEMM include files | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM - MICROSOFT Expanded Memory Manager | ||
| 11 | ; | ||
| 12 | ; Module: MEMMINC.ASM - lists all MEMM include files | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: June 14, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ; 06/25/86 original | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; Functional Description: | ||
| 31 | ; This module includes all MEMM include files and will | ||
| 32 | ; provide a listing of all when assembled to produce a listing file. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | .lfcond | ||
| 36 | .386p | ||
| 37 | |||
| 38 | ;****************************************************************************** | ||
| 39 | ; I N C L U D E S | ||
| 40 | ;****************************************************************************** | ||
| 41 | INC_LIST EQU 1 ; list include files | ||
| 42 | |||
| 43 | page | ||
| 44 | include ASCII_SM.EQU | ||
| 45 | page | ||
| 46 | include DRIVER.EQU | ||
| 47 | page | ||
| 48 | include PIC_DEF.EQU | ||
| 49 | page | ||
| 50 | include ROMSTRUC.EQU | ||
| 51 | page | ||
| 52 | include ROMXBIOS.EQU | ||
| 53 | |||
| 54 | page | ||
| 55 | include DESC.INC | ||
| 56 | page | ||
| 57 | include ELIM.INC | ||
| 58 | page | ||
| 59 | include EMM386.INC | ||
| 60 | page | ||
| 61 | include INSTR386.INC | ||
| 62 | page | ||
| 63 | include KBD.INC | ||
| 64 | page | ||
| 65 | include LOADALL.INC | ||
| 66 | page | ||
| 67 | include OEMDEP.INC | ||
| 68 | page | ||
| 69 | include PAGE.INC | ||
| 70 | page | ||
| 71 | include VDMSEG.INC | ||
| 72 | page | ||
| 73 | include VDMSEL.INC | ||
| 74 | page | ||
| 75 | include VM386.INC | ||
| 76 | |||
| 77 | page | ||
| 78 | include DRIVER.STR | ||
| 79 | |||
| 80 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMMONF.ASM b/v4.0/src/MEMM/MEMM/MEMMONF.ASM new file mode 100644 index 0000000..5eee389 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMMONF.ASM | |||
| @@ -0,0 +1,337 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MEMMONF - (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 11 | ; | ||
| 12 | ; Module: MEMMONF - parse for on/off/auto and perform the function | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: June 4, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/04/86 Original | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; | ||
| 31 | ; Functional Description: | ||
| 32 | ; MEMMONF is used by MEMM.EXE UTILITY code and MEMM.COM to parse | ||
| 33 | ; the command line for ON, OFF, or AUTO and perform the function | ||
| 34 | ; via a call to ELIM_Entry. It also displays the appropriate message | ||
| 35 | ; depending on the results of the parsing and call to ELIM_Entry. | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | page | ||
| 41 | ;****************************************************************************** | ||
| 42 | ; P U B L I C D E C L A R A T I O N S | ||
| 43 | ;****************************************************************************** | ||
| 44 | ; | ||
| 45 | public onf_func | ||
| 46 | public get_token | ||
| 47 | ; | ||
| 48 | ;****************************************************************************** | ||
| 49 | ; E X T E R N A L R E F E R E N C E S | ||
| 50 | ;****************************************************************************** | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | _TEXT segment byte use16 public 'CODE' | ||
| 55 | extrn Inst_chk:near | ||
| 56 | extrn ELIM_link:near | ||
| 57 | _TEXT ends | ||
| 58 | ; | ||
| 59 | page | ||
| 60 | ;****************************************************************************** | ||
| 61 | ; L O C A L C O N S T A N T S | ||
| 62 | ;****************************************************************************** | ||
| 63 | ; | ||
| 64 | MSDOS equ 21h ; MS-DOS function call | ||
| 65 | |||
| 66 | include ascii_sm.equ | ||
| 67 | |||
| 68 | ;****************************************************************************** | ||
| 69 | ; S E G M E N T D E F I N I T I O N | ||
| 70 | ;****************************************************************************** | ||
| 71 | ; | ||
| 72 | _TEXT segment byte use16 public 'CODE' | ||
| 73 | assume cs:_TEXT, ds:_TEXT, es:_TEXT, ss:_TEXT | ||
| 74 | ; | ||
| 75 | ;****************************************************************************** | ||
| 76 | ; L O C A L D A T A A R E A | ||
| 77 | ;****************************************************************************** | ||
| 78 | ; | ||
| 79 | include memm_msg.inc | ||
| 80 | ; | ||
| 81 | msg_tbl label word ; table of final messages to display | ||
| 82 | dw offset vmode ; on | ||
| 83 | dw offset rmode ; off | ||
| 84 | dw offset amode ; auto | ||
| 85 | dw 0 ; no parameter will use above msgs | ||
| 86 | dw offset parmerr ; invalid parameter | ||
| 87 | dw offset verr_msg ; error entering vmode | ||
| 88 | dw offset rerr ; error entering rmode | ||
| 89 | dw offset aerr ; error entering amode | ||
| 90 | ; | ||
| 91 | ; the valid arguments | ||
| 92 | ; | ||
| 93 | on_arg db "on" | ||
| 94 | on_len equ (this byte - on_arg) | ||
| 95 | |||
| 96 | off_arg db "off" | ||
| 97 | off_len equ (this byte - off_arg) | ||
| 98 | |||
| 99 | auto_arg db "auto" | ||
| 100 | auto_len equ (this byte - auto_arg) | ||
| 101 | |||
| 102 | null_arg db " " | ||
| 103 | null_len equ 1 | ||
| 104 | max_arg_len equ 11 | ||
| 105 | arg_str db max_arg_len dup(0) ; storage for get_token | ||
| 106 | ; | ||
| 107 | arg_tbl label word ; table of valid arguments | ||
| 108 | dw offset on_arg | ||
| 109 | dw offset off_arg | ||
| 110 | dw offset auto_arg | ||
| 111 | ; | ||
| 112 | no_arg equ (this byte - arg_tbl) | ||
| 113 | dw offset null_arg ; should be last entry | ||
| 114 | max_args equ (this byte - arg_tbl) | ||
| 115 | ; | ||
| 116 | arg_len label word ; table of argument lengths | ||
| 117 | dw on_len | ||
| 118 | dw off_len | ||
| 119 | dw auto_len | ||
| 120 | ; | ||
| 121 | dw null_len | ||
| 122 | |||
| 123 | page | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; onf_func - Check command line for ON OFF or AUTO and perform function | ||
| 126 | ; | ||
| 127 | ; ENTRY: es:di points to command line terminated by CR or LF | ||
| 128 | ; | ||
| 129 | ; EXIT: The appropriate message is displayed | ||
| 130 | ; | ||
| 131 | ; USED: none | ||
| 132 | ; | ||
| 133 | ;****************************************************************************** | ||
| 134 | onf_func proc near | ||
| 135 | |||
| 136 | push ax | ||
| 137 | push dx | ||
| 138 | push di | ||
| 139 | |||
| 140 | cld | ||
| 141 | ; | ||
| 142 | ; check for driver installed | ||
| 143 | ; | ||
| 144 | call Inst_chk ; ax = 0/1 => isn't/is installed | ||
| 145 | or ax,ax ; q: is it installed? | ||
| 146 | jnz drvr_installed | ||
| 147 | mov dx,offset not_there ; Not installed message | ||
| 148 | jmp term ; display message and quit | ||
| 149 | ; | ||
| 150 | drvr_installed: | ||
| 151 | ; | ||
| 152 | call parse_onf ; look for ON/OFF | ||
| 153 | jc msg_disp ; invalid parameter | ||
| 154 | cmp ax,no_arg/2 ; q: no argument? | ||
| 155 | je get_status ; y: get status | ||
| 156 | push ax ; save on/off indicator | ||
| 157 | mov ah,1 ; ah=1 for set status routine | ||
| 158 | call ELIM_link ; go turn it on or off | ||
| 159 | pop ax ; restore on/off indicator | ||
| 160 | jnc get_status ; no error in status routine | ||
| 161 | add ax,max_args/2+1 ; indicate error | ||
| 162 | jmp msg_disp | ||
| 163 | ; | ||
| 164 | get_status: | ||
| 165 | xor ah,ah ; get status | ||
| 166 | call ELIM_link ; status in ah | ||
| 167 | mov al,ah | ||
| 168 | xor ah,ah ; status in ax | ||
| 169 | cmp ax,2 ; q: auto mode? | ||
| 170 | jb msg_disp ; n: display mode | ||
| 171 | push ax ; save it | ||
| 172 | mov dx,offset amode | ||
| 173 | mov ah,9 | ||
| 174 | int MSDOS ; print auto mode | ||
| 175 | pop ax ; restore mode | ||
| 176 | sub ax,2 ; get on or off indicator | ||
| 177 | ; | ||
| 178 | msg_disp: | ||
| 179 | shl ax,1 ; make it a word index | ||
| 180 | mov di,ax ; offset into message table | ||
| 181 | mov dx,msg_tbl[di] ; get appropriate message | ||
| 182 | term: | ||
| 183 | mov ah,9 | ||
| 184 | int MSDOS ; display error message | ||
| 185 | ; | ||
| 186 | pop di | ||
| 187 | pop dx | ||
| 188 | pop ax | ||
| 189 | |||
| 190 | ret | ||
| 191 | onf_func endp | ||
| 192 | |||
| 193 | page | ||
| 194 | ;****************************************************************************** | ||
| 195 | ; get_token - Retrieve a non-white-space string from a source string | ||
| 196 | ; | ||
| 197 | ; ENTRY: es:di points to command line terminated by CR or LF | ||
| 198 | ; ds:si points to storage for token | ||
| 199 | ; cx = maximum length to store | ||
| 200 | ; | ||
| 201 | ; EXIT: cx = length of token (0 => end of source string) | ||
| 202 | ; es:di points to first char after new token in source string | ||
| 203 | ; string of length cx stored in ds:si (and converted to lower case) | ||
| 204 | ; | ||
| 205 | ; USED: see above | ||
| 206 | ; | ||
| 207 | ;****************************************************************************** | ||
| 208 | get_token proc near | ||
| 209 | push si ; save storage area | ||
| 210 | push bx | ||
| 211 | push ax | ||
| 212 | ; | ||
| 213 | mov bx,cx ; number to store | ||
| 214 | xor cx,cx ; no chars found so far | ||
| 215 | ; | ||
| 216 | ; go to first non-blank character | ||
| 217 | ; | ||
| 218 | gloop1: | ||
| 219 | mov al,es:[di] ; get a character | ||
| 220 | inc di ; point to next | ||
| 221 | cmp al,' ' ; Q: space ? | ||
| 222 | je gloop1 ; y: skip it | ||
| 223 | cmp al,TAB ; Q: TAB ? | ||
| 224 | je gloop1 ; y: skip it | ||
| 225 | dec di ; N: start parsing and reset di | ||
| 226 | gloop2: | ||
| 227 | mov al,es:[di] ; get next char | ||
| 228 | cmp al,CR ; q: carriage return? | ||
| 229 | je token_xit ; y: quit | ||
| 230 | cmp al,LF ; q: line feed? | ||
| 231 | je token_xit ; y: quit | ||
| 232 | cmp al,' ' ; Q: space ? | ||
| 233 | je token_xit ; y: quit | ||
| 234 | cmp al,TAB ; Q: TAB ? | ||
| 235 | je token_xit ; y: quit | ||
| 236 | inc di ; n: point to next | ||
| 237 | inc cx ; increment number of chars found | ||
| 238 | cmp cx,bx ; q: have we stored our limit yet? | ||
| 239 | ja gloop2 ; y: don't store any more | ||
| 240 | or al,20h ; make it lower case | ||
| 241 | mov ds:[si],al ; store it | ||
| 242 | inc si ; and point to next | ||
| 243 | jmp short gloop2 ; continue | ||
| 244 | token_xit: | ||
| 245 | ; | ||
| 246 | pop ax | ||
| 247 | pop bx | ||
| 248 | pop si | ||
| 249 | ret | ||
| 250 | get_token endp | ||
| 251 | |||
| 252 | page | ||
| 253 | ;****************************************************************************** | ||
| 254 | ; parse_onf - Parse command line for ON or OFF | ||
| 255 | ; | ||
| 256 | ; ENTRY: es:di points to command line terminated by CR or LF | ||
| 257 | ; | ||
| 258 | ; EXIT: ax = 0 => ON | ||
| 259 | ; ax = 1 => OFF | ||
| 260 | ; ax = 2 => AUTO | ||
| 261 | ; ax = 3 => no argument encountered | ||
| 262 | ; ax = 4 => Error in command line | ||
| 263 | ; CARRY = cleared if no errors | ||
| 264 | ; set if error (ax will also = 4) | ||
| 265 | ; es:di points to end of parsed string | ||
| 266 | ; | ||
| 267 | ; USED: see above | ||
| 268 | ; | ||
| 269 | ;****************************************************************************** | ||
| 270 | parse_onf proc near | ||
| 271 | ; | ||
| 272 | push si | ||
| 273 | push ds | ||
| 274 | push bx | ||
| 275 | push es | ||
| 276 | ; | ||
| 277 | mov bx,no_arg ; initialize to no parameters encountered | ||
| 278 | cld ; go foward | ||
| 279 | ; | ||
| 280 | ; es:di = 1st char | ||
| 281 | ; | ||
| 282 | mov si,offset arg_str ; ds:si = storage for argument | ||
| 283 | push cs | ||
| 284 | pop ds ; arg storage in _CODE | ||
| 285 | mov cx,max_arg_len ; maximum argument length | ||
| 286 | call get_token ; get an argument | ||
| 287 | or cx,cx ; q: any parms? | ||
| 288 | jz parse_xit ; n: quit | ||
| 289 | push di ; y: save di for later | ||
| 290 | push ds ; es:di = parameter table | ||
| 291 | pop es | ||
| 292 | |||
| 293 | xor bx,bx ; index into parameter table | ||
| 294 | ploop2: | ||
| 295 | cmp cx,arg_len[bx] ; q: lengths equal? | ||
| 296 | jne not_found ; n: keep looking | ||
| 297 | mov di,arg_tbl[bx] ; get destination address | ||
| 298 | push si ; save source string addr | ||
| 299 | repe cmpsb ; q: is this a valid argument? | ||
| 300 | pop si ; restore source string address (command line) | ||
| 301 | je found ; y: matched one | ||
| 302 | not_found: | ||
| 303 | inc bx | ||
| 304 | inc bx ; update table pointer | ||
| 305 | cmp bx,max_args ; q: have we done them all yet? | ||
| 306 | jne ploop2 ; n: keep looking | ||
| 307 | parse_inv: | ||
| 308 | mov bx,max_args ; y: invalid | ||
| 309 | pop di ; restore di | ||
| 310 | jmp short parse_xit ; leave | ||
| 311 | found: | ||
| 312 | pop di ; restore original string addr | ||
| 313 | pop es | ||
| 314 | mov cx,1 ; just need to check for one non blank | ||
| 315 | call get_token ; get another token | ||
| 316 | or cx,cx ; q: was there another one? | ||
| 317 | jz parse_xit2 ; n: good | ||
| 318 | mov bx,max_args ; y: invalid | ||
| 319 | jmp short parse_xit2 | ||
| 320 | parse_xit: | ||
| 321 | pop es | ||
| 322 | parse_xit2: | ||
| 323 | shr bx,1 ; get result of parse | ||
| 324 | mov ax,bx ; put in ax | ||
| 325 | mov bx,max_args/2-1 | ||
| 326 | cmp bx,ax ; set/clear carry on invalid/valid return | ||
| 327 | ; | ||
| 328 | pop bx | ||
| 329 | pop ds | ||
| 330 | pop si | ||
| 331 | ; | ||
| 332 | ret | ||
| 333 | parse_onf endp | ||
| 334 | |||
| 335 | _TEXT ends | ||
| 336 | |||
| 337 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/MEMM_MSG.INC b/v4.0/src/MEMM/MEMM/MEMM_MSG.INC new file mode 100644 index 0000000..da17c94 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MEMM_MSG.INC | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - 386 EMM device driver | ||
| 8 | ; | ||
| 9 | ; Module: CEM_MSG.INC - messages for ON/OFF/AUTO utility | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 7,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change Log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION Description | ||
| 22 | ; -------- -------- -------------------------------------------- | ||
| 23 | ; 06/07/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; | ||
| 28 | not_there db "EMM386 driver not installed.",CR,LF,BEL,"$" | ||
| 29 | |||
| 30 | vmode db "EMM386 Active.",CR,LF,"$" | ||
| 31 | |||
| 32 | rmode db "EMM386 Inactive.",CR,LF,"$" | ||
| 33 | |||
| 34 | amode db "EMM386 in Auto mode.",CR,LF,"$" | ||
| 35 | |||
| 36 | verr_msg db "Unable to activate EMM386.",CR,LF,BEL,"$" | ||
| 37 | |||
| 38 | rerr db "Unable to inactivate EMM386.",CR,LF,BEL,"$" | ||
| 39 | |||
| 40 | aerr db "Unable to place EMM386 in Auto mode.",CR,LF,BEL,"$" | ||
| 41 | |||
| 42 | parmerr db "Usage: EMM386 [ ON | OFF | AUTO]" | ||
| 43 | db CR,LF,BEL,"$" | ||
diff --git a/v4.0/src/MEMM/MEMM/MOVEB.ASM b/v4.0/src/MEMM/MEMM/MOVEB.ASM new file mode 100644 index 0000000..00b9a07 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/MOVEB.ASM | |||
| @@ -0,0 +1,533 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title MOVEB - move block emulator | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: MOVEB - move block code for MEMM | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: 05/22/86 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;************************************************************************* | ||
| 21 | ; CHANGE LOG: | ||
| 22 | ; DATE VERSION Description | ||
| 23 | ;--------- -------- -------------------------------------------------- | ||
| 24 | ; 05/15/86 Check source/target selector using verr,verw | ||
| 25 | ; and add parity handler | ||
| 26 | ; 06/09/86 Added MapLinear call | ||
| 27 | ; 06/17/86 Added code to detect and "handle" writes to | ||
| 28 | ; diag byte location. | ||
| 29 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 30 | ; 07/06/86 0.04 DiagByte moved to _DATA | ||
| 31 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 32 | ; 07/10/86 0.05 Added Real Mode patch code | ||
| 33 | ;************************************************************************* | ||
| 34 | .386p | ||
| 35 | |||
| 36 | |||
| 37 | ;**************************************** | ||
| 38 | ; P U B L I C S | ||
| 39 | ;**************************************** | ||
| 40 | public Move_Block | ||
| 41 | public MB_Exit | ||
| 42 | public MB_Stat | ||
| 43 | public i15_Entry | ||
| 44 | public MB_Flag | ||
| 45 | public i15_Old | ||
| 46 | |||
| 47 | page | ||
| 48 | ;**************************************** | ||
| 49 | ; D E F I N E S | ||
| 50 | ;**************************************** | ||
| 51 | include vdmseg.inc | ||
| 52 | include vdmsel.inc | ||
| 53 | include desc.inc | ||
| 54 | include instr386.inc | ||
| 55 | include oemdep.inc | ||
| 56 | include vm386.inc | ||
| 57 | |||
| 58 | TRUE equ 0FFh | ||
| 59 | FALSE equ 00h | ||
| 60 | |||
| 61 | D_G_BIT equ 80h ; granularity bit in high status bits | ||
| 62 | |||
| 63 | FLAGS_CY equ 0001h | ||
| 64 | FLAGS_ZF equ 0040h | ||
| 65 | FLAGS_IF equ 0200h | ||
| 66 | |||
| 67 | ; 386 data descriptor format | ||
| 68 | DATA_DESC_386 struc | ||
| 69 | DD386_Limit_lo dw ? ; low word of seg limit | ||
| 70 | DD386_Base_lo dw ? ; low 24 bits of seg base addr | ||
| 71 | db ? ; | ||
| 72 | DD386_Access db ? ; access byte | ||
| 73 | DD386_L_Stat db ? ; high 4 bits of seg limit | ||
| 74 | ; and futher status | ||
| 75 | DD386_Base_hi db ? ; high 8 bits of seg base addr | ||
| 76 | DATA_DESC_386 ends | ||
| 77 | |||
| 78 | ; format of move block descriptor table passed on entry | ||
| 79 | MB_GDT struc | ||
| 80 | MG_dummy dd 2 dup (?) ; dummy descriptor entry | ||
| 81 | MG_GDT dd 2 dup (?) ; GDT entry | ||
| 82 | MG_Source dd 2 dup (?) ; source segment entry | ||
| 83 | MG_Target dd 2 dup (?) ; target segment entry | ||
| 84 | MB_GDT ends | ||
| 85 | |||
| 86 | ;************************************************************ | ||
| 87 | ; DescrMap - map address in descriptor | ||
| 88 | ; ENTRY: ES:DI = descriptor | ||
| 89 | ; EXIT: descriptor's address is mapped by MapLinear | ||
| 90 | ; USED: EAX | ||
| 91 | ;************************************************************ | ||
| 92 | DescrMap MACRO | ||
| 93 | mov ah,ES:[di.DD386_Base_hi] ; ah = high 8 bits of address | ||
| 94 | mov al,byte ptr ES:[di.DD386_Base_lo+2] ; al = bits 16-23 of addr | ||
| 95 | OP32 | ||
| 96 | shl ax,16 ; high addr word into high EAX | ||
| 97 | mov ax,ES:[di.DD386_Base_lo] ; EAX = 32 bit address | ||
| 98 | call MapLinear ; map linear address | ||
| 99 | mov ES:[di.DD386_Base_lo],ax ; store low word of address | ||
| 100 | OP32 | ||
| 101 | shr ax,16 ; ax = high word of address | ||
| 102 | mov byte ptr ES:[di.DD386_Base_lo+2],al ; store | ||
| 103 | mov ES:[di.DD386_Base_hi],ah ; high word of address | ||
| 104 | ENDM | ||
| 105 | |||
| 106 | ;******************************************************************************* | ||
| 107 | ; E X T E R N A L R E F E R E N C E S | ||
| 108 | ;******************************************************************************* | ||
| 109 | _TEXT segment | ||
| 110 | |||
| 111 | extrn MapLinear:near | ||
| 112 | extrn Set_Par_Vect:near | ||
| 113 | extrn Rest_Par_Vect:near | ||
| 114 | extrn togl_A20:near | ||
| 115 | extrn get_a20_state:near | ||
| 116 | |||
| 117 | _TEXT ends | ||
| 118 | |||
| 119 | _DATA segment | ||
| 120 | |||
| 121 | extrn Active_Status:byte ; non-zero if in VM | ||
| 122 | |||
| 123 | _DATA ends | ||
| 124 | |||
| 125 | |||
| 126 | page | ||
| 127 | ;******************************************************************************* | ||
| 128 | ; D A T A S E G M E N T | ||
| 129 | ;******************************************************************************* | ||
| 130 | _DATA segment | ||
| 131 | |||
| 132 | MB_Stat db 0 ; move block status | ||
| 133 | Toggle_st db 0 | ||
| 134 | |||
| 135 | _DATA ends | ||
| 136 | |||
| 137 | page | ||
| 138 | ;**************************************** | ||
| 139 | ; C O D E S E G M E N T _TEXT | ||
| 140 | ;**************************************** | ||
| 141 | _TEXT segment | ||
| 142 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 143 | |||
| 144 | page | ||
| 145 | ;************************************************************************* | ||
| 146 | ;*** Move_Block - Mimics the 286 ROM function Move Block ( int15h AH=87h ). | ||
| 147 | ; Move a block of data (copy it) to/from anywhere in | ||
| 148 | ; 24bits of linear address space. Normally used to move | ||
| 149 | ; data to/from extended memory (past 1M) since real mode | ||
| 150 | ; can only address the first meg of memory. | ||
| 151 | ; | ||
| 152 | ; | ||
| 153 | ; ENTRY PROTECTED MODE | ||
| 154 | ; AH = 87h | ||
| 155 | ; CX = # of words to move ( max 8000h ). | ||
| 156 | ; ES:SI = ptr to a descriptor table containing segment descriptors | ||
| 157 | ; for the source and target memory of the transfer. | ||
| 158 | ; | ||
| 159 | ; EXIT PROTECTED MODE | ||
| 160 | ; AH = 00 if OK | ||
| 161 | ; 01 if parity error *** currently not checked *** | ||
| 162 | ; 02 if exception error | ||
| 163 | ; 03 if gate address bit A20 fails. | ||
| 164 | ; if no error: | ||
| 165 | ; ZF and NC in client's flags | ||
| 166 | ; if error: | ||
| 167 | ; NZ and CY in client's flags | ||
| 168 | ; | ||
| 169 | ; | ||
| 170 | ; USES AX, FLAGS -> CLD. | ||
| 171 | ; | ||
| 172 | ; Descriptor Table Format | ||
| 173 | ; ES:SI ---> +-------------------------------+ | ||
| 174 | ; | Dummy descriptor | | ||
| 175 | ; +-------------------------------+ | ||
| 176 | ; | GDT descriptor | | ||
| 177 | ; +-------------------------------+ | ||
| 178 | ; | Source segment descriptor | | ||
| 179 | ; +-------------------------------+ | ||
| 180 | ; | Target segment descriptor | | ||
| 181 | ; +-------------------------------+ | ||
| 182 | ; | ||
| 183 | ;************************************************************************* | ||
| 184 | Move_Block proc near | ||
| 185 | ; | ||
| 186 | push ds | ||
| 187 | push es | ||
| 188 | PUSH_EAX | ||
| 189 | push cx | ||
| 190 | push si | ||
| 191 | push di | ||
| 192 | ; | ||
| 193 | cld | ||
| 194 | ; | ||
| 195 | mov ax,VDMD_GSEL ; get data selector | ||
| 196 | mov ds,ax ; DS = DGROUP | ||
| 197 | mov [MB_Stat],0 ; init status of move block to OK. | ||
| 198 | ; | ||
| 199 | ; check word count field | ||
| 200 | ; | ||
| 201 | cmp cx,8000h ;Q: word count too high | ||
| 202 | jbe MB_chk_length ; N: check length of segments | ||
| 203 | jmp MB_Excp_Error ; Y: report exception error | ||
| 204 | |||
| 205 | ; | ||
| 206 | ; check source and target descriptor's lengths against transfer count | ||
| 207 | ; only need check low word since caller set up a 286 descriptor | ||
| 208 | ; | ||
| 209 | MB_chk_length: | ||
| 210 | mov ax,cx | ||
| 211 | shl ax,1 ; AX = # of bytes to transfer(0=>8000h) | ||
| 212 | dec ax ; convert to seg limit type value | ||
| 213 | ; ( 0FFFFh => 64K ) | ||
| 214 | cmp ax,ES:[si.MG_Source.DD386_Limit_lo] ;Q: source seg limit low ? | ||
| 215 | jbe MB_chk_tarl ; N: chk target length | ||
| 216 | jmp MB_Excp_Error ; Y: return excp error. | ||
| 217 | |||
| 218 | MB_chk_tarl: | ||
| 219 | cmp ax,ES:[si.MG_Target.DD386_Limit_lo] ;Q: tar seg too small ? | ||
| 220 | jbe MB_setup ; N: seg limits OK. | ||
| 221 | jmp MB_Excp_Error ; Y: return excp error | ||
| 222 | ; | ||
| 223 | ; source and target descriptors OK, set up scratch selector descriptors | ||
| 224 | ; | ||
| 225 | |||
| 226 | MB_setup: | ||
| 227 | push cx ; save copy count | ||
| 228 | |||
| 229 | push es | ||
| 230 | pop ds ; set DS:SI to input descriptor table | ||
| 231 | mov ax,GDTD_GSEL | ||
| 232 | mov es,ax ; ES:0 pts to GDT | ||
| 233 | mov di,MBSRC_GSEL ; ES:DI pts to source work descriptor in GDT | ||
| 234 | push si ; save input descr table ptr | ||
| 235 | lea si,[si.MG_Source]; DS:SI pts to input source descr | ||
| 236 | mov cx,4 | ||
| 237 | rep movsw ; set move block source work descr | ||
| 238 | pop si ; restore input descr table ptr | ||
| 239 | mov di,MBSRC_GSEL ; ES:DI pts to source work descriptor in GDT | ||
| 240 | call MB_Map_Src | ||
| 241 | DescrMap ; fixup this descriptor's linear address | ||
| 242 | |||
| 243 | mov di,MBTAR_GSEL ; ES:DI pts to target work descr in GDT | ||
| 244 | push si ; save input descr table ptr | ||
| 245 | lea si,[si.MG_Target] ; DS:SI pts to input target descr | ||
| 246 | mov cx,4 | ||
| 247 | rep movsw ; set move blk target work descr | ||
| 248 | pop si ; restore input descr table ptr | ||
| 249 | mov di,MBTAR_GSEL ; ES:DI pts to target work descr in GDT | ||
| 250 | call MB_Map_Dest | ||
| 251 | DescrMap ; fixup this descriptor's linear address | ||
| 252 | |||
| 253 | ; | ||
| 254 | ; install NMI/parity exception handler | ||
| 255 | ; | ||
| 256 | call Set_Par_Vect ; restore the parity interrupt handler | ||
| 257 | |||
| 258 | ; | ||
| 259 | ; copy the data | ||
| 260 | ; | ||
| 261 | |||
| 262 | ; | ||
| 263 | ; check if a20 line is to be enabled or not | ||
| 264 | ; | ||
| 265 | call get_a20_state | ||
| 266 | jnz a20_is_enb | ||
| 267 | ; | ||
| 268 | ; a20 line is currently disabled. we need to enable the a20 | ||
| 269 | ; | ||
| 270 | call togl_a20 | ||
| 271 | mov [toggle_st],0ffh | ||
| 272 | a20_is_enb: | ||
| 273 | ; | ||
| 274 | pop cx ; restore copy count | ||
| 275 | |||
| 276 | xor di,di | ||
| 277 | xor si,si | ||
| 278 | mov ax,MBSRC_GSEL | ||
| 279 | verr ax ;Q: source selector valid ? | ||
| 280 | jnz MB_Excp_Error ; N: return exception error | ||
| 281 | mov ds,ax ; Y: DS:SI pts to source segment | ||
| 282 | mov ax,MBTAR_GSEL | ||
| 283 | verw ax ;Q: target selector valid ? | ||
| 284 | jnz MB_Excp_Error ; N: return exception error | ||
| 285 | mov es,ax ; Y: ES:DI pts to target segment | ||
| 286 | jmp MB_move_block ; and go ahead | ||
| 287 | ; | ||
| 288 | ; Error reporting | ||
| 289 | ; | ||
| 290 | MB_Excp_Error: | ||
| 291 | mov ax,VDMD_GSEL ; get data selector | ||
| 292 | mov ds,ax ; DS = DGROUP | ||
| 293 | mov [MB_Stat],2 | ||
| 294 | jmp MB_Exit | ||
| 295 | ; | ||
| 296 | ; move the block | ||
| 297 | ; | ||
| 298 | MB_move_block: | ||
| 299 | |||
| 300 | call MB_Start | ||
| 301 | |||
| 302 | ; | ||
| 303 | ; MOVE the BLOCK - dwords | ||
| 304 | ; | ||
| 305 | test cx,01h ;Q: move an odd # of words? | ||
| 306 | jz MB_moved ; N: move dwords | ||
| 307 | movsw ; Y: move the first one => dwords now | ||
| 308 | MB_moved: | ||
| 309 | shr cx,1 ; move CX dwords... | ||
| 310 | OP32 | ||
| 311 | rep movsw ; REP MOVSD | ||
| 312 | |||
| 313 | mov ax,VDMD_GSEL ; get data selector | ||
| 314 | mov ds,ax ; DS = DGROUP | ||
| 315 | |||
| 316 | ; restore a20 state to what it was before this routine | ||
| 317 | ; | ||
| 318 | test [toggle_st],0ffh ; do we need to toggle the a20 back? | ||
| 319 | jz a20_restored ; N: skip toggling | ||
| 320 | call togl_a20 ; Y: else toggle the A20 line | ||
| 321 | a20_restored: | ||
| 322 | mov [toggle_st],0 ; clear this flag | ||
| 323 | |||
| 324 | jmp MB_Exit | ||
| 325 | Move_Block endp | ||
| 326 | |||
| 327 | ;************************************************************************* | ||
| 328 | ; This is special JUMP entry point for parity handler | ||
| 329 | ; | ||
| 330 | MB_Exit proc near | ||
| 331 | ; | ||
| 332 | ; reset NMI handler | ||
| 333 | ; | ||
| 334 | |||
| 335 | call Rest_Par_Vect ; restore the parity interrupt handler | ||
| 336 | |||
| 337 | ; | ||
| 338 | ; | ||
| 339 | MB_leave: | ||
| 340 | pop di | ||
| 341 | pop si | ||
| 342 | pop cx | ||
| 343 | POP_EAX | ||
| 344 | mov ah,[MB_Stat] | ||
| 345 | ; | ||
| 346 | ; set client's flags to no error | ||
| 347 | ; | ||
| 348 | or [bp.VTFOE+VMTF_EFLAGS],FLAGS_ZF ; ZF | ||
| 349 | and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_CY ; NC | ||
| 350 | |||
| 351 | or ah,ah ;Q: error occured ? | ||
| 352 | jz MB_ret ; N: continue | ||
| 353 | ; Y: set error in client's flags | ||
| 354 | and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_ZF ; NZ | ||
| 355 | or [bp.VTFOE+VMTF_EFLAGS],FLAGS_CY ; CY | ||
| 356 | ; | ||
| 357 | MB_ret: | ||
| 358 | pop es | ||
| 359 | pop ds | ||
| 360 | ret | ||
| 361 | ; | ||
| 362 | MB_Exit endp | ||
| 363 | |||
| 364 | _TEXT ends | ||
| 365 | |||
| 366 | page | ||
| 367 | ;**************************************** | ||
| 368 | ; C O D E S E G M E N T R_CODE | ||
| 369 | ;**************************************** | ||
| 370 | R_CODE segment | ||
| 371 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 372 | |||
| 373 | ;************************************************************************* | ||
| 374 | ; local data | ||
| 375 | ;************************************************************************* | ||
| 376 | I15_Old dd 0 ; old Int 15h handler | ||
| 377 | MB_Flag db 0 ; non-zero => do move block in ring 0 | ||
| 378 | Exit_Flags dw 0 ; flags for int15 exit | ||
| 379 | ; | ||
| 380 | ext_mem_size dw 0 ; we are using new int 15 allocation | ||
| 381 | ; scheme now whereby we have to lower | ||
| 382 | ; the size reported by int 15 function | ||
| 383 | ; 88h to grab some memory for ourself | ||
| 384 | ; The extended memory allocate routine | ||
| 385 | ; in allocmem.asm fills in the approp. | ||
| 386 | ; size here. | ||
| 387 | |||
| 388 | page | ||
| 389 | ;************************************************************************* | ||
| 390 | ; i15_Entry - real/virtual mode patch code for int 15h | ||
| 391 | ; | ||
| 392 | ; This function patches the real mode IDT for MEMM. If it is | ||
| 393 | ; entered for a move block, this code sets a flag to tell MEMM to | ||
| 394 | ; pick up the move block, then i15_Entry lets MEMM do it. Otherwise | ||
| 395 | ; MEMM jumps to the previous code. For function 88h it reports the | ||
| 396 | ; the new size of extended memory. | ||
| 397 | ; | ||
| 398 | ; ENTRY Real/Virtual mode | ||
| 399 | ; see int15h entry parameters in ROM spec | ||
| 400 | ; | ||
| 401 | ; EXIT | ||
| 402 | ; | ||
| 403 | ; 87h: Real/Virtual mode | ||
| 404 | ; AH = 00 if OK | ||
| 405 | ; 01 if parity error *** currently not checked *** | ||
| 406 | ; 02 if exception error | ||
| 407 | ; 03 if gate address bit A20 fails. | ||
| 408 | ; if no error: | ||
| 409 | ; ZF and NC in client's flags | ||
| 410 | ; if error: | ||
| 411 | ; NZ and CY in client's flags | ||
| 412 | ; | ||
| 413 | ; 88h: Real/Virtual mode | ||
| 414 | ; AX = Size of extended memory in KB | ||
| 415 | ; | ||
| 416 | ; | ||
| 417 | ; USES AX, FLAGS -> CLD. | ||
| 418 | ; | ||
| 419 | ; NOTE:**ISP This routine was modified to implement the new INT15 allocation | ||
| 420 | ; scheme whereby MEMM by lowering the size of extended memory could | ||
| 421 | ; grab the difference between the old size and the new size reported | ||
| 422 | ; for itself. | ||
| 423 | ;************************************************************************* | ||
| 424 | i15_flags equ 6 | ||
| 425 | i15_cs equ 4 | ||
| 426 | i15_ip equ 2 | ||
| 427 | i15_bp equ 0 | ||
| 428 | |||
| 429 | i15_Entry proc near | ||
| 430 | ; | ||
| 431 | cli ; in case of pushf/call far | ||
| 432 | pushf ; save entry flags | ||
| 433 | ; | ||
| 434 | ; Check to see if it is the extended memory size request | ||
| 435 | ; | ||
| 436 | cmp ah,88h ;Q: extended memory size request? | ||
| 437 | jne chk_blk_move ; N: go to check for move block call | ||
| 438 | ; | ||
| 439 | ; Implement int15 allocation scheme by reporting a lowered value of extended | ||
| 440 | ; memory. | ||
| 441 | popf | ||
| 442 | mov ax,cs:[ext_mem_size] ; report new extended memory size | ||
| 443 | iret ; | ||
| 444 | ; | ||
| 445 | ; Checking for move block call | ||
| 446 | ; | ||
| 447 | chk_blk_move: | ||
| 448 | cmp ah,87h ;Q: move block call ? | ||
| 449 | jne i15_jmpf ; N: jmp to old code | ||
| 450 | push ds | ||
| 451 | push seg DGROUP ; | ||
| 452 | pop ds ; DS -> DOSGROUP | ||
| 453 | cmp [Active_Status],0 ; Y: Q: in Virtual mode ? | ||
| 454 | pop ds ; reset DS | ||
| 455 | je i15_jmpf ; N: jmp to old code | ||
| 456 | ; Y: VM move block | ||
| 457 | mov CS:[MB_Flag],TRUE ; let MEMM have it ... | ||
| 458 | popf ; retrieve entry flags (IF cleared!!!) | ||
| 459 | int 15h ; give it to MEMM | ||
| 460 | ; MEMM will reset MB_Flag | ||
| 461 | cli ; just in case | ||
| 462 | push bp ; save bp | ||
| 463 | mov bp,sp | ||
| 464 | push ax ; save ax | ||
| 465 | pushf | ||
| 466 | pop ax ; AX = exit flags | ||
| 467 | xchg ax,[bp+i15_Flags] ; AX = entry flag, exit flags on stack | ||
| 468 | and ax,FLAGS_IF ; save only IF bit of entry | ||
| 469 | or [bp+i15_Flags],ax ; set IF state in flags on stack | ||
| 470 | pop ax | ||
| 471 | pop bp | ||
| 472 | iret ; and leave | ||
| 473 | ; | ||
| 474 | ; far jump to old code | ||
| 475 | ; | ||
| 476 | i15_jmpf: | ||
| 477 | popf ; retrieve entry flags | ||
| 478 | jmp CS:[i15_Old] | ||
| 479 | ; | ||
| 480 | i15_Entry endp | ||
| 481 | |||
| 482 | R_CODE ends | ||
| 483 | |||
| 484 | |||
| 485 | LAST SEGMENT | ||
| 486 | ; | ||
| 487 | ASSUME CS:LAST | ||
| 488 | ; | ||
| 489 | public set_ext | ||
| 490 | ; | ||
| 491 | ;************************************************************************* | ||
| 492 | ; set_ext - to fill up size of extended memory reported by int 15 | ||
| 493 | ; | ||
| 494 | ; This function fills up the size of extended memory reported by the | ||
| 495 | ; int 15 real/virtual mode patch. | ||
| 496 | ; | ||
| 497 | ; ENTRY Real Mode | ||
| 498 | ; bx=size of extended memory in Kb | ||
| 499 | ; | ||
| 500 | ; EXIT None. R_CODE:ext_mem_size filled. | ||
| 501 | ; | ||
| 502 | ; USES None. | ||
| 503 | ; | ||
| 504 | ; WRITTEN 7/25/88 ISP | ||
| 505 | ; | ||
| 506 | ;************************************************************************* | ||
| 507 | |||
| 508 | set_ext proc near | ||
| 509 | ; | ||
| 510 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 511 | |||
| 512 | push ax | ||
| 513 | push ds | ||
| 514 | ; | ||
| 515 | mov ax,seg R_CODE | ||
| 516 | mov ds,ax | ||
| 517 | ; | ||
| 518 | ASSUME DS:R_CODE | ||
| 519 | ; | ||
| 520 | mov [ext_mem_size],bx | ||
| 521 | ; | ||
| 522 | pop ds | ||
| 523 | pop ax | ||
| 524 | ; | ||
| 525 | ASSUME DS:NOTHING | ||
| 526 | ; | ||
| 527 | ret | ||
| 528 | ; | ||
| 529 | set_ext endp | ||
| 530 | ; | ||
| 531 | |||
| 532 | LAST ENDS | ||
| 533 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/M_STATE.ASM b/v4.0/src/MEMM/MEMM/M_STATE.ASM new file mode 100644 index 0000000..9961558 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/M_STATE.ASM | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE M_STATE:MODULE to establish machine state at emm boot time | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: M_STATE | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Aug 29,1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP (ISP) | ||
| 19 | ;****************************************************************************** | ||
| 20 | ; | ||
| 21 | ; Change Log: | ||
| 22 | ; | ||
| 23 | ; DATE REVISION Description | ||
| 24 | ; -------- -------- -------------------------------------------- | ||
| 25 | ;****************************************************************************** | ||
| 26 | ; Functional Description: | ||
| 27 | ; | ||
| 28 | ;****************************************************************************** | ||
| 29 | .lfcond | ||
| 30 | .386p | ||
| 31 | |||
| 32 | page | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; P U B L I C D E C L A R A T I O N S | ||
| 35 | ;****************************************************************************** | ||
| 36 | |||
| 37 | public estb_mach_state | ||
| 38 | |||
| 39 | page | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; L O C A L C O N S T A N T S | ||
| 42 | ;****************************************************************************** | ||
| 43 | ; | ||
| 44 | |||
| 45 | ;****************************************************************************** | ||
| 46 | ; INCLUDE FILES | ||
| 47 | ;****************************************************************************** | ||
| 48 | include vdmseg.inc ; segment definitions | ||
| 49 | |||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; E X T E R N A L R E F E R E N C E S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | ; | ||
| 56 | _DATA segment | ||
| 57 | _DATA ends | ||
| 58 | |||
| 59 | ; | ||
| 60 | LAST segment | ||
| 61 | ; | ||
| 62 | extrn estb_a20_state:near | ||
| 63 | ; | ||
| 64 | LAST ends | ||
| 65 | |||
| 66 | page | ||
| 67 | ;****************************************************************************** | ||
| 68 | ; S E G M E N T D E F I N I T I O N | ||
| 69 | ;****************************************************************************** | ||
| 70 | |||
| 71 | |||
| 72 | ;****************************************************************************** | ||
| 73 | ; | ||
| 74 | ; Code Segments | ||
| 75 | ; | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; | ||
| 78 | _TEXT segment | ||
| 79 | _TEXT ends | ||
| 80 | |||
| 81 | LAST segment | ||
| 82 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 83 | |||
| 84 | page | ||
| 85 | ;-----------------------------------------------------------------------; | ||
| 86 | ; estb_mach_state ; | ||
| 87 | ; ; | ||
| 88 | ; establishes the state of the machine at memm boot. the only thing we ; | ||
| 89 | ; are concerned about right now is the a20 state which needs to be ; | ||
| 90 | ; preserved via emulation ; | ||
| 91 | ; ; | ||
| 92 | ; Arguments: ; | ||
| 93 | ; nothing ; | ||
| 94 | ; Returns: ; | ||
| 95 | ; nothing ; | ||
| 96 | ; Alters: ; | ||
| 97 | ; flags ; | ||
| 98 | ; Calls: ; | ||
| 99 | ; estb_a20_state ; | ||
| 100 | ; History: ; | ||
| 101 | ; ISP (isp). ; | ||
| 102 | ;-----------------------------------------------------------------------; | ||
| 103 | estb_mach_state proc near | ||
| 104 | ; | ||
| 105 | call estb_a20_state | ||
| 106 | ret | ||
| 107 | ; | ||
| 108 | estb_mach_state endp | ||
| 109 | |||
| 110 | LAST ends ; End of segment | ||
| 111 | ; | ||
| 112 | |||
| 113 | end ; End of module | ||
| 114 | |||
diff --git a/v4.0/src/MEMM/MEMM/OEMDEP.INC b/v4.0/src/MEMM/MEMM/OEMDEP.INC new file mode 100644 index 0000000..0a2607d --- /dev/null +++ b/v4.0/src/MEMM/MEMM/OEMDEP.INC | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: OEMDEP.INC | ||
| 10 | ; | ||
| 11 | ; Version: 0.04 | ||
| 12 | ; | ||
| 13 | ; Date: June 13, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/13/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; 07/05/86 0.04 Moved Diagbyte to _DATA | ||
| 26 | ; 07/06/86 0.04 Change from _DATA assume to DGROUP | ||
| 27 | ; 08/06/86 0.05 Broke out OEMPROC.ASM from OEMDEP.INC | ||
| 28 | ; | ||
| 29 | ;****************************************************************************** | ||
| 30 | ifndef INC_LIST | ||
| 31 | .xlist | ||
| 32 | endif | ||
| 33 | |||
| 34 | |||
| 35 | _TEXT segment | ||
| 36 | |||
| 37 | extrn MaskIntAll:near ; Mask interrupts routine | ||
| 38 | extrn RestIntMask:near ; restore interrupt mask routine | ||
| 39 | |||
| 40 | extrn Map_Lin_OEM:near ; MapLinear hook | ||
| 41 | extrn UMap_Lin_OEM:near ; UnMapLinear hook | ||
| 42 | extrn MB_Map_Src:near ; Move block map source hook | ||
| 43 | extrn MB_Map_Dest:near ; Move block map destination hook | ||
| 44 | extrn MB_Start:near ; Move block start move hook | ||
| 45 | |||
| 46 | _TEXT ends | ||
| 47 | |||
| 48 | |||
| 49 | LAST segment | ||
| 50 | |||
| 51 | extrn VerifyMachine:near ; Verify machine valid for software | ||
| 52 | |||
| 53 | LAST ends | ||
| 54 | |||
| 55 | ifndef NOHIMEM ; only for high memory | ||
| 56 | |||
| 57 | ;Define routines in OEMPROC module | ||
| 58 | |||
| 59 | _TEXT segment | ||
| 60 | |||
| 61 | extrn HwMemLock:near | ||
| 62 | extrn HwMemUnlock:near | ||
| 63 | |||
| 64 | _TEXT ends | ||
| 65 | |||
| 66 | LAST segment | ||
| 67 | |||
| 68 | extrn hbuf_chk:near | ||
| 69 | extrn HiAlloc:near | ||
| 70 | extrn HiSysAlloc:near | ||
| 71 | extrn HImod:near | ||
| 72 | extrn LockROM:near | ||
| 73 | extrn UnLockROM:near | ||
| 74 | |||
| 75 | LAST ends | ||
| 76 | |||
| 77 | endif | ||
| 78 | |||
| 79 | ;****************************************************************************** | ||
| 80 | ; | ||
| 81 | ; HwTabUnlock - unlocks high system RAM - makes tables writeable | ||
| 82 | ; | ||
| 83 | ; EXIT: FS points to DIAG segment | ||
| 84 | ; high system RAM writeable | ||
| 85 | ; | ||
| 86 | HwTabUnlock MACRO | ||
| 87 | ifndef NOHIMEM ; only for high memory | ||
| 88 | call HwMemUnlock | ||
| 89 | endif | ||
| 90 | ENDM | ||
| 91 | |||
| 92 | ;****************************************************************************** | ||
| 93 | ; | ||
| 94 | ; HwTabLock - update client's hi system RAM write locks state | ||
| 95 | ; | ||
| 96 | ; ENTRY: CS = _TEXT | ||
| 97 | ; CS:[DiagByte] = last byte written to diag byte by user. | ||
| 98 | ; | ||
| 99 | ; EXIT: high system RAM write protect ON or OFF depenending on | ||
| 100 | ; write protect bit in CS:[DiagByte]. | ||
| 101 | ; Bit 1 = 0 => write protect ON | ||
| 102 | ; Bit 1 = 1 => write protect OFF | ||
| 103 | ; | ||
| 104 | HwTabLock MACRO | ||
| 105 | ifndef NOHIMEM ; only for high memory | ||
| 106 | call HwMemLock | ||
| 107 | endif | ||
| 108 | |||
| 109 | ENDM | ||
| 110 | |||
| 111 | .list ; end of OEMDEP.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/OEMPROC.ASM b/v4.0/src/MEMM/MEMM/OEMPROC.ASM new file mode 100644 index 0000000..b5e4931 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/OEMPROC.ASM | |||
| @@ -0,0 +1,1120 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: OEMPROC.ASM | ||
| 10 | ; | ||
| 11 | ; Version: 0.05 | ||
| 12 | ; | ||
| 13 | ; Date: June 13, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/13/86 Original Separated out OEMPROC from OEMDEP.INC | ||
| 24 | ; | ||
| 25 | ;****************************************************************************** | ||
| 26 | ; | ||
| 27 | .386p | ||
| 28 | .lfcond ; list false conditionals | ||
| 29 | |||
| 30 | public VerifyMachine | ||
| 31 | public MaskIntAll | ||
| 32 | public RestIntMask | ||
| 33 | public OEM_Trap_Init | ||
| 34 | public Map_Lin_OEM | ||
| 35 | public UMap_Lin_OEM | ||
| 36 | public MB_Map_Src | ||
| 37 | public MB_Map_Dest | ||
| 38 | public MB_Start | ||
| 39 | public Rest_Par_Vect | ||
| 40 | public Set_Par_Vect | ||
| 41 | |||
| 42 | public DisableNMI | ||
| 43 | public ROM_BIOS_Machine_ID | ||
| 44 | public OEM_Init_Diag_Page | ||
| 45 | |||
| 46 | |||
| 47 | ifndef NOHIMEM | ||
| 48 | |||
| 49 | public hi_size | ||
| 50 | public hi_alloc | ||
| 51 | public hisys_alloc | ||
| 52 | |||
| 53 | public HwMemLock | ||
| 54 | public HwMemUnlock | ||
| 55 | |||
| 56 | public Hi_Mem_Size | ||
| 57 | public hbuf_chk | ||
| 58 | public HiAlloc | ||
| 59 | public HiSysAlloc | ||
| 60 | public HImod | ||
| 61 | |||
| 62 | public InitLock | ||
| 63 | public LockROM | ||
| 64 | public UnLockROM | ||
| 65 | |||
| 66 | |||
| 67 | endif | ||
| 68 | |||
| 69 | include page.inc | ||
| 70 | include vdmseg.inc | ||
| 71 | include VDMsel.inc | ||
| 72 | include desc.inc | ||
| 73 | include Instr386.inc | ||
| 74 | include romxbios.equ | ||
| 75 | |||
| 76 | |||
| 77 | ;****************************************************************************** | ||
| 78 | ; E X T E R N A L R E F E R E N C E S | ||
| 79 | ;****************************************************************************** | ||
| 80 | ; | ||
| 81 | _DATA segment | ||
| 82 | extrn gdt_mb:word | ||
| 83 | extrn MB_Stat:word | ||
| 84 | _DATA ends | ||
| 85 | |||
| 86 | |||
| 87 | LAST segment | ||
| 88 | extrn set_src_selector:near | ||
| 89 | extrn set_dest_selector:near | ||
| 90 | extrn SetPageEntry:near | ||
| 91 | LAST ends | ||
| 92 | |||
| 93 | _TEXT segment | ||
| 94 | extrn MB_Exit:near | ||
| 95 | _TEXT ends | ||
| 96 | |||
| 97 | page | ||
| 98 | ;****************************************************************************** | ||
| 99 | ; L O C A L C O N S T A N T S | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; | ||
| 102 | |||
| 103 | MASTER_IMR equ 21h ; mask port for master 8259 | ||
| 104 | |||
| 105 | ; | ||
| 106 | ; PPI port bit definitions | ||
| 107 | ; | ||
| 108 | PPI equ 61h | ||
| 109 | PPO equ 61h | ||
| 110 | PPO_MASK_IOCHECK equ 04h ; disable system board parity check | ||
| 111 | PPO_MASK_PCHECK equ 08h ; disable IO parity check | ||
| 112 | |||
| 113 | RTC_CMD equ 70h ; Real Time Clock cmd port | ||
| 114 | DISABLE_NMI equ 80h ; mask bit for NMI | ||
| 115 | ENABLE_NMI equ 00h ; this command to RTC_CMD enables NMI | ||
| 116 | |||
| 117 | ;****** REMOVE BEFORE DISTRIBUTION begin | ||
| 118 | ; Compaq specific 386 related addresses | ||
| 119 | ; | ||
| 120 | X_HI_MEM_SEG equ 0f000h ;segment for the following words | ||
| 121 | X_MT_386 equ 0fffeh ; Machine type | ||
| 122 | X_RT_386 equ 0ffe8h ; Rom type | ||
| 123 | X_HI_PTR equ 0ffe0h ; pointer to four words (offsets below) | ||
| 124 | X_MEM_BOARD equ 0 ; 32-bit memory board status word | ||
| 125 | X_HISYS equ 0 ; low byte = # of free 4k system pages | ||
| 126 | X_AVAIL_MEM equ 4 ; available hi memory in 16 byte chunks | ||
| 127 | X_LAST_HI equ 6 ; last used byte in hi memory (grows down) | ||
| 128 | ; | ||
| 129 | ; Addresses and values used to write the "ROM" | ||
| 130 | ; | ||
| 131 | OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr | ||
| 132 | LOCK_ADR_LO equ 0000h ; 0:15 of 32-bit location | ||
| 133 | LOCK_ADR_HI equ OEM_MEM_HI ; 16-31 of 32-bit location | ||
| 134 | LOCK_ROM equ 0fcfch ; value to write to lock rom | ||
| 135 | UNLOCK_ROM equ 0fefeh ; value to write to unlock rom | ||
| 136 | |||
| 137 | |||
| 138 | |||
| 139 | DIAGSEG segment use16 at 0 | ||
| 140 | DiagLoc dw ? ; 32 bit memory board diagnostic byte | ||
| 141 | DIAGSEG ends | ||
| 142 | |||
| 143 | |||
| 144 | ; | ||
| 145 | ; data definitions | ||
| 146 | ; | ||
| 147 | _DATA segment | ||
| 148 | |||
| 149 | NMI_Old db 8 dup (0) ; save area for old NMI handler | ||
| 150 | |||
| 151 | NMI_New label byte ; descriptor for new NMI handler | ||
| 152 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:Parity_Handler>,D_386INT0 | ||
| 153 | |||
| 154 | ; | ||
| 155 | ifndef NOHIMEM ; if high memory in this model | ||
| 156 | ;Next two entries MUST stay together! | ||
| 157 | hbase_addr_l dw 0000h ; 24 bit address of beginning of hi memory | ||
| 158 | hbase_addr_h db 00h ; pool of EMM pages. | ||
| 159 | ; | ||
| 160 | hi_size dw 0 ; size of hi memory in kbytes | ||
| 161 | hi_alloc dw 0 ; actual hi memory allocated (due to potential waste) | ||
| 162 | hisys_alloc dw 0 ; amount of hi system memory allocated in 4k bytes | ||
| 163 | ; | ||
| 164 | DiagAddr db 0 ; set this when writting to diag byte location | ||
| 165 | DiagByte db LOW LOCK_ROM ; most recent diag byte written by user | ||
| 166 | buffer dw 0 ; buffer for 1 word move blocks | ||
| 167 | endif | ||
| 168 | |||
| 169 | |||
| 170 | int_mask db ? ; save for restoring masked interrupts | ||
| 171 | |||
| 172 | ; | ||
| 173 | ROM_BIOS_Machine_ID db 0fch ; hard coded right now to AT model byte. | ||
| 174 | ; should be changed to be initialised at | ||
| 175 | ; init time ...isp | ||
| 176 | |||
| 177 | |||
| 178 | _DATA ends | ||
| 179 | ;****** REMOVE BEFORE DISTRIBUTION end | ||
| 180 | |||
| 181 | |||
| 182 | _TEXT segment | ||
| 183 | ASSUME CS:_TEXT, DS:DGROUP | ||
| 184 | |||
| 185 | ;****************************************************************************** | ||
| 186 | ; | ||
| 187 | ; MaskIntAll Save current interrupt mask state and mask all interrupts | ||
| 188 | ; | ||
| 189 | ; entry: DS pts to DGROUP | ||
| 190 | ; | ||
| 191 | ; exit: All interrupts disabled | ||
| 192 | ; | ||
| 193 | ; used: AX | ||
| 194 | ; | ||
| 195 | ; stack: | ||
| 196 | ; | ||
| 197 | ;****************************************************************************** | ||
| 198 | MaskIntAll proc near | ||
| 199 | in al,MASTER_IMR | ||
| 200 | mov [int_mask], al | ||
| 201 | mov al,0ffh ;;; all OFF | ||
| 202 | out MASTER_IMR,al | ||
| 203 | ret | ||
| 204 | MaskIntAll endp | ||
| 205 | |||
| 206 | ;****************************************************************************** | ||
| 207 | ; | ||
| 208 | ; RestIntMask Restore interrupt mask saved in MaskIntAll | ||
| 209 | ; | ||
| 210 | ; entry: DS pts to DGROUP | ||
| 211 | ; | ||
| 212 | ; exit: Interrupts restored to state previous to MaskIntAll | ||
| 213 | ; | ||
| 214 | ; used: AX | ||
| 215 | ; | ||
| 216 | ; stack: | ||
| 217 | ; | ||
| 218 | ;****************************************************************************** | ||
| 219 | RestIntMask proc near | ||
| 220 | mov al,[int_mask] ; restore interrupt mask | ||
| 221 | out MASTER_IMR,al | ||
| 222 | ret | ||
| 223 | RestIntMask endp | ||
| 224 | |||
| 225 | ;****************************************************************************** | ||
| 226 | ; OEM_Trap_Init - turn on I/O bit map trapping for I/O port watching | ||
| 227 | ; | ||
| 228 | ; ENTRY: DS -> DGROUP - real,virtual, or protected mode | ||
| 229 | ; ES -> TSS segment | ||
| 230 | ; Trap_Tab already has address of OEM_Handler for ??? ports | ||
| 231 | ; | ||
| 232 | ; Description: This routine is used to initialize any data structures, | ||
| 233 | ; including the IOBitMap(via PortTrap call) used for trapping I/O ports | ||
| 234 | ; when going into virtual mode. The routine(s) used to handle the | ||
| 235 | ; trap(s) should already be installed in the IOTrap_tab table. | ||
| 236 | ; See RRTrap.asm for an example. | ||
| 237 | ; | ||
| 238 | ; EXIT: IO_BitMap Updated to trap ports used for ??? | ||
| 239 | ; | ||
| 240 | ; USED: AX,Flags | ||
| 241 | ; STACK: | ||
| 242 | ;------------------------------------------------------------------------------ | ||
| 243 | assume cs:_TEXT, ds:DGROUP, es:TSS | ||
| 244 | OEM_Trap_Init proc near | ||
| 245 | ; | ||
| 246 | ; Initialize data structures | ||
| 247 | ; | ||
| 248 | ; | ||
| 249 | ; Set IOBM traps to look for client's disabling of the A20 line | ||
| 250 | ; | ||
| 251 | ; push bx | ||
| 252 | ; mov bh, 80h ; set every 1k | ||
| 253 | ; mov ax, ??? ; AX = port num to trap | ||
| 254 | ; call PortTrap ; set traps on ??? port | ||
| 255 | ; | ||
| 256 | ; mov ax,0FFFFh | ||
| 257 | ; mov [???],ax ; Initialize trap data structure | ||
| 258 | ; pop bx | ||
| 259 | |||
| 260 | ret | ||
| 261 | ; | ||
| 262 | OEM_Trap_Init endp | ||
| 263 | ; | ||
| 264 | |||
| 265 | ifndef NOHIMEM ; only for high memory | ||
| 266 | |||
| 267 | ;****************************************************************************** | ||
| 268 | ; | ||
| 269 | ; HwMemUnlock - unlocks high system RAM - makes tables writeable | ||
| 270 | ; | ||
| 271 | ; ENTRY: None | ||
| 272 | ; | ||
| 273 | ; EXIT: If NOHIMEM, does nothing, else: | ||
| 274 | ; FS points to DIAG segment | ||
| 275 | ; high system RAM writeable | ||
| 276 | ; | ||
| 277 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 278 | HwMemUnlock proc near | ||
| 279 | push OEM0_GSEL | ||
| 280 | POP_FS ; set FS to diag segment | ||
| 281 | ASSUME DS:DIAGSEG | ||
| 282 | FSOVER | ||
| 283 | mov word ptr [DiagLoc],UNLOCK_ROM | ||
| 284 | ret | ||
| 285 | HwMemUnlock endp | ||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | ;****************************************************************************** | ||
| 290 | ; | ||
| 291 | ; HwMemLock - update client's hi system RAM write locks state | ||
| 292 | ; | ||
| 293 | ; ENTRY: CS = _TEXT(Protected mode) | ||
| 294 | ; DGROUP:[DiagByte] = last byte written to diag byte by user. | ||
| 295 | ; | ||
| 296 | ; EXIT: high system RAM write protect ON or OFF depenending on | ||
| 297 | ; write protect bit in CS:[DiagByte]. | ||
| 298 | ; Bit 1 = 0 => write protect ON | ||
| 299 | ; Bit 1 = 1 => write protect OFF | ||
| 300 | ; | ||
| 301 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 302 | HwMemLock proc near | ||
| 303 | |||
| 304 | push VDMD_GSEL | ||
| 305 | POP_FS ; FS = DGROUP | ||
| 306 | assume ds:DGROUP | ||
| 307 | FSOVER | ||
| 308 | test [DiagByte],02h ;Q: client's ROM write protected? | ||
| 309 | |||
| 310 | push OEM0_GSEL | ||
| 311 | POP_FS ; set FS to diag segment | ||
| 312 | ASSUME DS:DIAGSEG | ||
| 313 | |||
| 314 | jz HTL_wp ; Y: then write protect ON | ||
| 315 | FSOVER ; N: then write protect OFF | ||
| 316 | mov word ptr [DiagLoc],UNLOCK_ROM | ||
| 317 | jmp short HTL_exit | ||
| 318 | HTL_wp: | ||
| 319 | FSOVER | ||
| 320 | mov word ptr [DiagLoc],LOCK_ROM | ||
| 321 | HTL_exit: | ||
| 322 | ret | ||
| 323 | HwMemLock endp | ||
| 324 | |||
| 325 | endif ;end of "high" memory routines(ifndef NOHIMEM) | ||
| 326 | |||
| 327 | ;****************************************************************************** | ||
| 328 | ; | ||
| 329 | ; Map_Lin_OEM Map OEM high memory from physical to linear address | ||
| 330 | ; | ||
| 331 | ; description: This maps an attempt to access the "high" memory to the | ||
| 332 | ; area starting at 16Meg, which the page tables map to the | ||
| 333 | ; proper physical address. | ||
| 334 | ; | ||
| 335 | ; entry: EAX = physical address to map to linear address | ||
| 336 | ; | ||
| 337 | ; exit: If address has been mapped in AX, CF = 1, else CF = 0. | ||
| 338 | ; | ||
| 339 | ; used: AX | ||
| 340 | ; | ||
| 341 | ; stack: | ||
| 342 | ; | ||
| 343 | ;****************************************************************************** | ||
| 344 | ; | ||
| 345 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 346 | Map_Lin_OEM proc near | ||
| 347 | OP32 | ||
| 348 | cmp ax,0000h | ||
| 349 | dw OEM_MEM_HI ;Q: Addr in diags byte region ? | ||
| 350 | clc | ||
| 351 | jne Mp_Lin_Exit ; N: return, CF = 0(no mapping done) | ||
| 352 | OP32 ; Y: set EAX to proper seg address for diags | ||
| 353 | sub ax,0000h | ||
| 354 | dw (OEM_MEM_HI - 0100h); move to 0100h segment | ||
| 355 | ifndef NOHIMEM | ||
| 356 | ; set write to diag byte flag | ||
| 357 | push ds ; save DS | ||
| 358 | push VDMD_GSEL | ||
| 359 | pop ds ; DS = DGROUP | ||
| 360 | ASSUME DS:DGROUP | ||
| 361 | mov [DiagAddr],1 ; set flag for diag addr | ||
| 362 | pop ds ; reset DS | ||
| 363 | endif | ||
| 364 | stc | ||
| 365 | Mp_Lin_Exit: | ||
| 366 | ret | ||
| 367 | Map_Lin_OEM endp | ||
| 368 | |||
| 369 | |||
| 370 | |||
| 371 | ;****************************************************************************** | ||
| 372 | ; | ||
| 373 | ; UMap_Lin_OEM Map OEM high memory from linear to physical address | ||
| 374 | ; | ||
| 375 | ; description: This maps an attempt to access the "high" memory in the | ||
| 376 | ; linear address area starting at 16Meg, to the proper physical | ||
| 377 | ; address. | ||
| 378 | ; | ||
| 379 | ; entry: EAX = linear address to map to physical address | ||
| 380 | ; | ||
| 381 | ; exit: EAX = physical address | ||
| 382 | ; | ||
| 383 | ; used: EAX | ||
| 384 | ; | ||
| 385 | ; stack: | ||
| 386 | ; | ||
| 387 | ;****************************************************************************** | ||
| 388 | ; | ||
| 389 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 390 | UMap_Lin_OEM proc near | ||
| 391 | OP32 ; Y: set EAX to physical address for diags | ||
| 392 | add ax,0000h | ||
| 393 | dw (OEM_MEM_HI - 0100h) ; move to OEM_MEM_HI segment | ||
| 394 | ret | ||
| 395 | UMap_Lin_OEM endp | ||
| 396 | |||
| 397 | ;****************************************************************************** | ||
| 398 | ; | ||
| 399 | ; MB_Map_Src Do special move block processing before source mapping | ||
| 400 | ; | ||
| 401 | ; description: | ||
| 402 | ; This routine is called just before MoveBlock does mapping of | ||
| 403 | ; the source. In conjunction with the Map_Lin_OEM routine, and | ||
| 404 | ; the MB_Start routine, it can perform special processing on the | ||
| 405 | ; data moved. | ||
| 406 | ; | ||
| 407 | ; entry: ES:DI pts to source work descr in GDT | ||
| 408 | ; | ||
| 409 | ; exit: any flag setting or perturbation of descriptor is done | ||
| 410 | ; | ||
| 411 | ; used: none | ||
| 412 | ; | ||
| 413 | ; stack: | ||
| 414 | ; | ||
| 415 | ;****************************************************************************** | ||
| 416 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 417 | MB_Map_Src proc near | ||
| 418 | ret | ||
| 419 | MB_Map_Src endp | ||
| 420 | |||
| 421 | ;****************************************************************************** | ||
| 422 | ; | ||
| 423 | ; MB_Map_Dest Do special move block processing before destination mapping | ||
| 424 | ; | ||
| 425 | ; description: | ||
| 426 | ; This routine is called just before MoveBlock does mapping of | ||
| 427 | ; the destination. In conjunction with the Map_Lin_OEM routine, | ||
| 428 | ; and the MB_Start routine, it can perform special processing on | ||
| 429 | ; the data moved. | ||
| 430 | ; | ||
| 431 | ; entry: ES:DI pts to destination work descr in GDT | ||
| 432 | ; | ||
| 433 | ; exit: any flag setting or perturbation of descriptor is done | ||
| 434 | ; | ||
| 435 | ; used: AX | ||
| 436 | ; | ||
| 437 | ; stack: | ||
| 438 | ; | ||
| 439 | ;****************************************************************************** | ||
| 440 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 441 | MB_Map_Dest proc near | ||
| 442 | ifndef NOHIMEM | ||
| 443 | push ds | ||
| 444 | push VDMD_GSEL | ||
| 445 | pop ds ; DS = DGROUP alias selector | ||
| 446 | ASSUME DS:DGROUP | ||
| 447 | mov [DiagAddr],0 ; reset diag addr flag before write | ||
| 448 | pop ds ; reset DS | ||
| 449 | endif | ||
| 450 | ret | ||
| 451 | MB_Map_Dest endp | ||
| 452 | |||
| 453 | ;****************************************************************************** | ||
| 454 | ; | ||
| 455 | ; MB_Start Do any special move block processing | ||
| 456 | ; | ||
| 457 | ; description: | ||
| 458 | ; This routine is called just before MoveBlock does the move. | ||
| 459 | ; It allows for any special processing of data moved | ||
| 460 | ; | ||
| 461 | ; entry: DS is source selector | ||
| 462 | ; ES is destination selector | ||
| 463 | ; SI is source offset | ||
| 464 | ; DI is destination offset | ||
| 465 | ; | ||
| 466 | ; exit: nothing | ||
| 467 | ; | ||
| 468 | ; used: AX | ||
| 469 | ; | ||
| 470 | ; stack: | ||
| 471 | ; | ||
| 472 | ;****************************************************************************** | ||
| 473 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 474 | MB_Start proc near | ||
| 475 | ifndef NOHIMEM | ||
| 476 | ; | ||
| 477 | ; check for write to diag byte location | ||
| 478 | ; | ||
| 479 | push es | ||
| 480 | push VDMD_GSEL | ||
| 481 | pop es ; ES = DGROUP alias | ||
| 482 | ASSUME ES:DGROUP | ||
| 483 | cmp es:[DiagAddr],0 ;Q: does target -> diag byte ? | ||
| 484 | je MB_nodiag ; N: then don't worry | ||
| 485 | mov al,[si] ; Y: get current diag byte | ||
| 486 | mov es:[DiagByte],al ; and save it where we can access it | ||
| 487 | MB_nodiag: | ||
| 488 | pop es ; restore es | ||
| 489 | endif | ||
| 490 | ret | ||
| 491 | MB_Start endp | ||
| 492 | |||
| 493 | ;************************************************************************* | ||
| 494 | ; Set_Par_Vect - Set parity handling routine to routine below | ||
| 495 | ; | ||
| 496 | ; Description: | ||
| 497 | ; This routine sets up a parity handling routine in case of | ||
| 498 | ; a parity error during a MOVEBLOCK. | ||
| 499 | ; | ||
| 500 | ; ENTRY: protected mode | ||
| 501 | ; | ||
| 502 | ; EXIT: vector restored | ||
| 503 | ; | ||
| 504 | ; USES: AX, CX, ES, DS, DI, SI | ||
| 505 | ; | ||
| 506 | ; note: entry is from protected mode -> DS,ES are same as during | ||
| 507 | ; move block. | ||
| 508 | ;************************************************************************* | ||
| 509 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 510 | Set_Par_Vect proc near | ||
| 511 | mov ax,VDMD_GSEL | ||
| 512 | mov es,ax ; ES pts to DGROUP | ||
| 513 | mov ax,IDTD_GSEL ; | ||
| 514 | mov ds,ax ; DS points to IDT | ||
| 515 | |||
| 516 | mov si,0010h ; DS:[SI] points to NMI descr address in IDT | ||
| 517 | mov di,offset DGROUP:NMI_Old ; ES:[DI] pts to store area | ||
| 518 | mov cx,2 | ||
| 519 | db 66h | ||
| 520 | rep movsw ; store 2 dwords - save current NMI descriptor | ||
| 521 | push ds | ||
| 522 | push es | ||
| 523 | pop ds ; DS = DGROUP | ||
| 524 | pop es ; ES = IDT | ||
| 525 | mov di,0010h ; ES:[DI] points to NMI descr address in IDT | ||
| 526 | mov si,offset DGROUP:NMI_New ; DS:[SI] pts to new NMI descr | ||
| 527 | mov cx,2 | ||
| 528 | db 66h | ||
| 529 | rep movsw ; set up new NMI descriptor in IDT | ||
| 530 | ret | ||
| 531 | Set_Par_Vect endp | ||
| 532 | |||
| 533 | ;************************************************************************* | ||
| 534 | ; Rest_Par_Vect - restore parity handling routine to original | ||
| 535 | ; | ||
| 536 | ; Description: | ||
| 537 | ; This routine restores the parity handling vector to the | ||
| 538 | ; contents before Set_Par_Vect was called. It is called after | ||
| 539 | ; a MOVEBLOCK has been completed. | ||
| 540 | ; | ||
| 541 | ; ENTRY: DS = DGROUP | ||
| 542 | ; | ||
| 543 | ; EXIT: vector restored | ||
| 544 | ; | ||
| 545 | ; USES: AX, CX, ES, DI, SI | ||
| 546 | ; | ||
| 547 | ; note: entry is from protected mode -> DS,ES are same as during | ||
| 548 | ; move block. | ||
| 549 | ;************************************************************************* | ||
| 550 | assume cs:_TEXT, ds:DGROUP, es:NOTHING | ||
| 551 | Rest_Par_Vect proc near | ||
| 552 | ifndef NOHIMEM | ||
| 553 | call HwMemUnlock ; in case IDT is in high mem | ||
| 554 | endif | ||
| 555 | mov ax,IDTD_GSEL ; selector for IDT | ||
| 556 | mov es,ax ; ES points to IDT | ||
| 557 | |||
| 558 | mov di,0010h ; ES:[DI] points to NMI descr address in IDT | ||
| 559 | mov si,offset DGROUP:NMI_Old ; DS:[SI] pts to store area | ||
| 560 | mov cx,2 | ||
| 561 | db 66h | ||
| 562 | rep movsw ; restore previous NMI descriptor | ||
| 563 | ifndef NOHIMEM | ||
| 564 | call HwMemLock | ||
| 565 | endif | ||
| 566 | ret | ||
| 567 | Rest_Par_Vect endp | ||
| 568 | |||
| 569 | |||
| 570 | ;************************************************************************* | ||
| 571 | ; Parity_Handler - routine to handle parity errors which occur during | ||
| 572 | ; move_block. | ||
| 573 | ; Description: | ||
| 574 | ; This routine writes to the parity error location to | ||
| 575 | ; clear the parity error on the memory board, then it clears | ||
| 576 | ; the parity error on the system board. | ||
| 577 | ; | ||
| 578 | ; note: entry is from protected mode -> DS,ES are same as during | ||
| 579 | ; move block. | ||
| 580 | ;************************************************************************* | ||
| 581 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 582 | Parity_Handler proc far | ||
| 583 | ; | ||
| 584 | dec si | ||
| 585 | dec si ;;; DS:SI pts to address causing parity error | ||
| 586 | mov ax,[si] ;;; retrieve value and write it back | ||
| 587 | mov [si],ax ;;; to reset parity on memory board. | ||
| 588 | in al,PPI ;;; Get parity error flags, reset then set | ||
| 589 | jmp $+2 ;;; parity checking to reset parity on | ||
| 590 | jmp $+2 ;;; system board | ||
| 591 | or al,PPO_MASK_IOCHECK ;;; disable IOCHECK | ||
| 592 | or al,PPO_MASK_PCHECK ;;; disable PCHECK | ||
| 593 | out PPO,al ;;; disable them | ||
| 594 | jmp $+2 | ||
| 595 | jmp $+2 | ||
| 596 | jmp $+2 | ||
| 597 | |||
| 598 | ifndef NOHIMEM | ||
| 599 | call HwMemlock ;;; LOCK high sys mem | ||
| 600 | endif | ||
| 601 | |||
| 602 | and al, NOT PPO_MASK_IOCHECK ;;; enable IOCHECK | ||
| 603 | and al, NOT PPO_MASK_PCHECK ;;; enable PCHECK | ||
| 604 | out PPO,al ;;; enable them | ||
| 605 | ;;; system board parity now reset | ||
| 606 | |||
| 607 | ; | ||
| 608 | mov ax,VDMD_GSEL ;;; | ||
| 609 | mov ds,ax ;;; set DS to data seg | ||
| 610 | assume ds:DGROUP | ||
| 611 | mov [MB_Stat],1 ;;; set parity error | ||
| 612 | add sp,12 ;;; remove NMI stuff from stack | ||
| 613 | jmp MB_Exit ;;; and exit move block | ||
| 614 | |||
| 615 | Parity_Handler endp | ||
| 616 | |||
| 617 | ;************************************************************************* | ||
| 618 | ; DisableNMI - This is called by the NMI handler to disable the | ||
| 619 | ; NMI interrupt(stop gracefully) as part of the | ||
| 620 | ; graceful handling of the NMI interrupt. | ||
| 621 | ; | ||
| 622 | ; Description: | ||
| 623 | ; | ||
| 624 | ; note: entry is from 386 protected mode | ||
| 625 | ;************************************************************************* | ||
| 626 | assume cs:_TEXT, ds:NOTHING, es:NOTHING | ||
| 627 | DisableNMI proc near | ||
| 628 | push ax | ||
| 629 | mov al,DISABLE_NMI | ||
| 630 | out RTC_CMD,al | ||
| 631 | pop ax | ||
| 632 | ret | ||
| 633 | DisableNMI endp | ||
| 634 | |||
| 635 | _TEXT ends | ||
| 636 | |||
| 637 | LAST segment | ||
| 638 | |||
| 639 | ;****************************************************************************** | ||
| 640 | ; | ||
| 641 | ; VerifyMachine Check ID, etc. to make sure machine is 386 valid for | ||
| 642 | ; running the LIM/386 product. | ||
| 643 | ; | ||
| 644 | ; description: | ||
| 645 | ; This routine should check ROM signature bytes and any other | ||
| 646 | ; hardware features that guarantee the appropriateness of running this | ||
| 647 | ; software on the machine. | ||
| 648 | ; | ||
| 649 | ; entry: DS pts to DGROUP | ||
| 650 | ; CF = 1 if from INIT procedure, CF = 0 if from AllocMem procedure | ||
| 651 | ; REAL or VIRTUAL MODE | ||
| 652 | ; | ||
| 653 | ; exit: If not correct machine, CF = 1, else CF = 0. | ||
| 654 | ; | ||
| 655 | ; used: AX | ||
| 656 | ; | ||
| 657 | ; stack: | ||
| 658 | ; | ||
| 659 | ;****************************************************************************** | ||
| 660 | ; | ||
| 661 | assume cs:LAST, ds:NOTHING, es:NOTHING | ||
| 662 | VerifyMachine proc near | ||
| 663 | pushf | ||
| 664 | push es ; save es | ||
| 665 | push bx ; save bx | ||
| 666 | mov bx,X_HI_MEM_SEG ; segment of hi memory control words | ||
| 667 | mov es,bx ; into es | ||
| 668 | mov ax,es:X_MT_386 ; get machine type | ||
| 669 | cmp al,0FCh ; q: is this an AT class machine? | ||
| 670 | mov ax,es:X_RT_386 ; get ROM type | ||
| 671 | pop bx ; restore bx | ||
| 672 | pop es ; restore es | ||
| 673 | jne inc_prcf ; n: invalid | ||
| 674 | popf | ||
| 675 | jc Cor_Prc ; that's all the checking for INIT | ||
| 676 | cmp ax,'30' ; q: is this a 386? (really '03') | ||
| 677 | jne inc_prc | ||
| 678 | Cor_Prc: | ||
| 679 | clc | ||
| 680 | ret | ||
| 681 | inc_prcf: | ||
| 682 | popf | ||
| 683 | inc_prc: | ||
| 684 | stc | ||
| 685 | ret | ||
| 686 | VerifyMachine endp ; End of procedure | ||
| 687 | |||
| 688 | |||
| 689 | ifndef NOHIMEM ; if high memory in this model | ||
| 690 | ;****************************************************************************** | ||
| 691 | ; | ||
| 692 | ; Hi_Mem_Size - returns pointer and size of high mem allocated to EMM | ||
| 693 | ; | ||
| 694 | ; entry: | ||
| 695 | ; | ||
| 696 | ; exit: if ZF = 1, no high memory allocated to EMM, else | ||
| 697 | ; EAX = 24 bit pointer to EMM allocated high memory | ||
| 698 | ; CX = kbytes of high memory allocated | ||
| 699 | ; | ||
| 700 | ; used: EAX, CX(returned values) | ||
| 701 | ; | ||
| 702 | ; stack: | ||
| 703 | ; | ||
| 704 | ;****************************************************************************** | ||
| 705 | ; | ||
| 706 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 707 | Hi_Mem_Size proc near | ||
| 708 | mov cx,[hi_size] ; CX = kbytes of high mem | ||
| 709 | shr cx,4 ;Q: any hi memory pages ? CX = pg cnt | ||
| 710 | jz Hi_Mem_SXit ; N: Exit with ZF = 1 | ||
| 711 | db 66h ; Y: get high memory pointers | ||
| 712 | mov ax,[hbase_addr_l] ; get pointer to high memory pool | ||
| 713 | db 66h | ||
| 714 | and ax,0FFFFh ; AND EAX,00FFFFFFh | ||
| 715 | dw 00FFh ; clear highest nibble | ||
| 716 | Hi_Mem_SXit: | ||
| 717 | ret | ||
| 718 | Hi_Mem_Size endp | ||
| 719 | |||
| 720 | page | ||
| 721 | ;****************************************************************************** | ||
| 722 | ; | ||
| 723 | ; hbuf_chk Hi memory pool check. | ||
| 724 | ; Check available hi memory pool space | ||
| 725 | ; | ||
| 726 | ; entry: | ||
| 727 | ; | ||
| 728 | ; exit: If hi memory pool space is available then | ||
| 729 | ; AX = size of memory available and CF = 0 | ||
| 730 | ; else AX = 0 and CF = 1 | ||
| 731 | ; | ||
| 732 | ; used: AX(returned value) | ||
| 733 | ; | ||
| 734 | ; stack: | ||
| 735 | ; | ||
| 736 | ;****************************************************************************** | ||
| 737 | ; | ||
| 738 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 739 | hbuf_chk proc near | ||
| 740 | push es ; save es | ||
| 741 | push bx | ||
| 742 | mov bx,X_HI_MEM_SEG ; segment of hi memory control words | ||
| 743 | mov es,bx | ||
| 744 | mov bx,es:X_HI_PTR ; pointer to hi memory control words | ||
| 745 | mov ax,es:[bx+X_MEM_BOARD] ; 32-bit memory board status | ||
| 746 | inc ax ; q: memory board status word == -1? | ||
| 747 | stc | ||
| 748 | jz hbuf_xit ; y: not installed | ||
| 749 | mov ax,es:[bx+X_AVAIL_MEM] ; get available memory in 16 byte pieces | ||
| 750 | mov bx,es:[bx+X_LAST_HI] ; get last used address | ||
| 751 | and bx,0ffh ; align to 4k byte boundary (2**8)*16 | ||
| 752 | sub ax,bx ; ax = available 16 byte pieces | ||
| 753 | shr ax,10 ; ax = available 16k byte pieces | ||
| 754 | shl ax,4 ; ax = available 1k byte pieces | ||
| 755 | clc | ||
| 756 | hbuf_xit: | ||
| 757 | pop bx ; ax = availble memory unless CF = 1 | ||
| 758 | pop es | ||
| 759 | ret | ||
| 760 | hbuf_chk endp | ||
| 761 | ; | ||
| 762 | page | ||
| 763 | ;****************************************************************************** | ||
| 764 | ; | ||
| 765 | ; HiAlloc - allocate hi memory - update hi memory control words | ||
| 766 | ; | ||
| 767 | ; entry: REAL or VIRTUAL MODE | ||
| 768 | ; DS pts to DGROUP | ||
| 769 | ; DGROUP:[hi_size] size in kbytes to allocate | ||
| 770 | ; | ||
| 771 | ; exit: update available hi memory and last used address. | ||
| 772 | ; Set [hbase_addr_l] and [hbase_addr_h] to starting address. | ||
| 773 | ; If error occurs in writing control words, CF = 1, else CF = 0. | ||
| 774 | ; | ||
| 775 | ; used: none | ||
| 776 | ; | ||
| 777 | ; stack: | ||
| 778 | ; | ||
| 779 | ;****************************************************************************** | ||
| 780 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 781 | HiAlloc proc near | ||
| 782 | ; | ||
| 783 | push ax | ||
| 784 | push bx | ||
| 785 | push cx | ||
| 786 | push dx | ||
| 787 | push si | ||
| 788 | push es | ||
| 789 | ; | ||
| 790 | mov ax,[hi_size] ; get amount of hi memory to allocate | ||
| 791 | or ax,ax ; q: allocate any? | ||
| 792 | jz Hi_xit ; n: quit(CF = 0) | ||
| 793 | |||
| 794 | mov cl,6 | ||
| 795 | shl ax,cl ; back to 16 byte pieces | ||
| 796 | ; | ||
| 797 | mov bx,X_HI_MEM_SEG ; high memory segment | ||
| 798 | mov es,bx | ||
| 799 | mov bx,es:X_HI_PTR ; pointer to high memory control words | ||
| 800 | mov cx,0ffh ; determine waste by aligning to 4k | ||
| 801 | and cx,es:[bx+X_LAST_HI] ; cx = extra needed to align | ||
| 802 | add ax,cx ; ax = total to allocate | ||
| 803 | mov [hi_alloc],ax ; save it in case we need to put it back | ||
| 804 | xor bx,bx ; bx = no hi system memory to alloc | ||
| 805 | call HImod ; go allocate it | ||
| 806 | ; ax = start of this hi memory | ||
| 807 | jc Hi_xit ; error occurred during move block(CF=1) | ||
| 808 | mov cx,16 | ||
| 809 | mul cx ; make it 24 bits | ||
| 810 | add dl,0f0h ; last 1M segment | ||
| 811 | mov [hbase_addr_h],dl ; save starting address of hi mem | ||
| 812 | mov [hbase_addr_l],ax | ||
| 813 | clc | ||
| 814 | ; | ||
| 815 | Hi_xit: ; CF = 1 if error, else CF = 0 | ||
| 816 | pop es | ||
| 817 | pop si | ||
| 818 | pop dx | ||
| 819 | pop cx | ||
| 820 | pop bx | ||
| 821 | pop ax | ||
| 822 | ret | ||
| 823 | HiAlloc endp | ||
| 824 | ; | ||
| 825 | page | ||
| 826 | ;****************************************************************************** | ||
| 827 | ; | ||
| 828 | ; HiSysAlloc - allocate hi system memory - update hi memory control words | ||
| 829 | ; | ||
| 830 | ; entry: REAL or VIRTUAL MODE | ||
| 831 | ; DS pts to DGROUP | ||
| 832 | ; ax = # of 4k byte pieces to allocate | ||
| 833 | ; | ||
| 834 | ; exit: If enough hi system memory available | ||
| 835 | ; update available hi system memory. | ||
| 836 | ; ax = # of 4k byte pieces used before this allocation. | ||
| 837 | ; CY cleared | ||
| 838 | ; else | ||
| 839 | ; ax = amount of hi system memory available | ||
| 840 | ; CY set | ||
| 841 | ; If error occurs in writing control words, | ||
| 842 | ; CY set | ||
| 843 | ; ax = -1 | ||
| 844 | ; | ||
| 845 | ; used: see above | ||
| 846 | ; | ||
| 847 | ; stack: | ||
| 848 | ; | ||
| 849 | ;****************************************************************************** | ||
| 850 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 851 | HiSysAlloc proc near | ||
| 852 | push bx | ||
| 853 | push es | ||
| 854 | ; | ||
| 855 | push ax ; save amount asked for | ||
| 856 | mov bx,X_HI_MEM_SEG ; high memory segment | ||
| 857 | mov es,bx | ||
| 858 | mov bx,es:X_HI_PTR ; pointer to high memory control words | ||
| 859 | mov ax,es:[bx+X_HISYS] ; ax = amount of hi system mem available | ||
| 860 | and ax,00ffh ; after we get rid of high byte | ||
| 861 | pop bx ; bx = amount requested | ||
| 862 | ; ax = amount currently available | ||
| 863 | cmp ax,bx ; Q: available >= requested? | ||
| 864 | jb Hisys_xit ; N: quit - carry set => not enough mem | ||
| 865 | add [hisys_alloc],bx ; Y: save it in case we must deallocate | ||
| 866 | push ax ; save amount available before | ||
| 867 | xor ax,ax ; ax = no hi user mem to alloc | ||
| 868 | call HImod ; go allocate high sys mem | ||
| 869 | pop bx ; bx = amount available before | ||
| 870 | jc Hisys_err ; MOD ERROR -> set error flag | ||
| 871 | mov ax,10h ; 16 pages in high sys mem pool | ||
| 872 | sub ax,bx ; ax = amount used before this request | ||
| 873 | jmp Hisys_xit ; no error in move block | ||
| 874 | ; | ||
| 875 | Hisys_err: | ||
| 876 | mov ax,-1 | ||
| 877 | stc ; to be sure | ||
| 878 | Hisys_xit: | ||
| 879 | pop es | ||
| 880 | pop bx | ||
| 881 | ret | ||
| 882 | HiSysAlloc endp | ||
| 883 | ; | ||
| 884 | page | ||
| 885 | ;****************************************************************************** | ||
| 886 | ; | ||
| 887 | ; Himod - allocate/deallocate hi memory - update hi memory control words | ||
| 888 | ; | ||
| 889 | ; entry: REAL or VIRTUAL MODE | ||
| 890 | ; DS pts to DGROUP | ||
| 891 | ; ax = size in 16 bytes of hi USER mem to alloc (a negative # | ||
| 892 | ; will deallocate) | ||
| 893 | ; bx = size in 4k bytes of hi SYSTEM mem to alloc (ditto above) | ||
| 894 | ; | ||
| 895 | ; exit: update available hi memory and last used address. | ||
| 896 | ; ax = New last used address for high user memory | ||
| 897 | ; CY = set if block move error occurred | ||
| 898 | ; | ||
| 899 | ; used: none | ||
| 900 | ; | ||
| 901 | ; stack: | ||
| 902 | ; | ||
| 903 | ;****************************************************************************** | ||
| 904 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 905 | HImod proc near | ||
| 906 | push bx | ||
| 907 | push cx | ||
| 908 | push dx | ||
| 909 | push si | ||
| 910 | push es | ||
| 911 | ; | ||
| 912 | call UnLockROM ;Q: ROM space writeable? | ||
| 913 | jz unlock_ok ; Y: continue | ||
| 914 | jmp Himod_err ; N: exit | ||
| 915 | unlock_ok: | ||
| 916 | push bx ; save hi system memory allocation | ||
| 917 | mov bx,X_HI_MEM_SEG ; high memory segment | ||
| 918 | mov es,bx | ||
| 919 | mov bx,es:X_HI_PTR ; pointer to high memory control words | ||
| 920 | sub es:[bx+X_AVAIL_MEM],ax ; update hi memory available | ||
| 921 | sub es:[bx+X_LAST_HI],ax ; and last used address | ||
| 922 | pop ax ; get hi system memory amount | ||
| 923 | sub es:[bx+X_HISYS],ax ; update hi system memory available | ||
| 924 | mov ax,es:[bx+X_LAST_HI] ; start of this hi memory | ||
| 925 | ; | ||
| 926 | call LockROM ;Q: ROM write protected now ? | ||
| 927 | clc ; clear error flag | ||
| 928 | jz Himod_xit ; Y: exit with no error | ||
| 929 | ; ; N: report error | ||
| 930 | Himod_err: | ||
| 931 | stc ; indicate error | ||
| 932 | HImod_xit: | ||
| 933 | pop es | ||
| 934 | pop si | ||
| 935 | pop dx | ||
| 936 | pop cx | ||
| 937 | pop bx | ||
| 938 | ; | ||
| 939 | ret | ||
| 940 | |||
| 941 | |||
| 942 | HImod endp | ||
| 943 | page | ||
| 944 | ;****************************************************************************** | ||
| 945 | ; | ||
| 946 | ; LockROM - write protects high system RAM | ||
| 947 | ; | ||
| 948 | ; entry: REAL or VIRTUAL MODE | ||
| 949 | ; DS pts to DGROUP | ||
| 950 | ; | ||
| 951 | ; exit: Z = no error - high system RAM write protected | ||
| 952 | ; NZ = ERROR. | ||
| 953 | ; | ||
| 954 | ; used: none | ||
| 955 | ; | ||
| 956 | ; stack: | ||
| 957 | ; | ||
| 958 | ;****************************************************************************** | ||
| 959 | assume cs:LAST, ds:DGROUP, es:NOTHING | ||
| 960 | LockROM proc near | ||
| 961 | push ax ; save ax | ||
| 962 | push cx | ||
| 963 | push dx | ||
| 964 | push es | ||
| 965 | ; | ||
| 966 | mov word ptr [buffer],LOCK_ROM ; word to write to unlock | ||
| 967 | jmp UL_write ; go write it... | ||
| 968 | ; | ||
| 969 | LockROM endp | ||
| 970 | |||
| 971 | page | ||
| 972 | ;****************************************************************************** | ||
| 973 | ; | ||
| 974 | ; UnLockROM - turns off write protect on high system RAM | ||
| 975 | ; | ||
| 976 | ; entry: REAL or VIRTUAL MODE | ||
| 977 | ; DS pts to DGROUP | ||
| 978 | ; | ||
| 979 | ; exit: Z = no error - high system RAM writeable | ||
| 980 | ; NZ = ERROR. | ||
| 981 | ; | ||
| 982 | ; used: none | ||
| 983 | ; | ||
| 984 | ; stack: | ||
| 985 | ; | ||
| 986 | ;****************************************************************************** | ||
| 987 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 988 | UnLockROM proc near | ||
| 989 | push ax ; save ax | ||
| 990 | push cx | ||
| 991 | push dx | ||
| 992 | push es | ||
| 993 | ; | ||
| 994 | mov word ptr [buffer],UNLOCK_ROM ; word to write to unlock | ||
| 995 | ; | ||
| 996 | UL_write: | ||
| 997 | mov ax,seg DGROUP ; set source addr to buffer | ||
| 998 | mov es,ax ; set ES to DGROUP | ||
| 999 | mov cx,16 | ||
| 1000 | mul cx ; make 24 bits | ||
| 1001 | add ax,offset DGROUP:buffer | ||
| 1002 | adc dl,0 | ||
| 1003 | mov cx,1 ; 1 word to transfer | ||
| 1004 | call set_src_selector ; set source segment selector to buffer | ||
| 1005 | mov ax,LOCK_ADR_LO ; DX:AX = 32-bit addr of ROM LOCK | ||
| 1006 | mov dx,LOCK_ADR_HI | ||
| 1007 | mov cx,1 ; 1 word long | ||
| 1008 | call set_dest_selector ; destination is unlock address | ||
| 1009 | |||
| 1010 | mov ax,seg LAST | ||
| 1011 | mov es,ax ; es to last segmetn | ||
| 1012 | mov si,offset DGROUP:gdt_mb ; ES:SI -> global descriptor table | ||
| 1013 | mov ah,MOVE_BLK ; int 15 block move function code | ||
| 1014 | int XBIOS ; unlock rom | ||
| 1015 | or ah,ah ; Q: error? | ||
| 1016 | ; Y: return NZ | ||
| 1017 | ; N: return Z | ||
| 1018 | pop es | ||
| 1019 | pop dx | ||
| 1020 | pop cx | ||
| 1021 | pop ax | ||
| 1022 | ret | ||
| 1023 | UnLockROM endp ; end of procedure | ||
| 1024 | |||
| 1025 | endif ; end of code for not NOHIMEM | ||
| 1026 | |||
| 1027 | |||
| 1028 | ;****************************************************************************** | ||
| 1029 | ; | ||
| 1030 | ; OEM_Init_Diag_Page: Initialise the 5th page table to point to the | ||
| 1031 | ; diagnostic segment. | ||
| 1032 | ; | ||
| 1033 | ; description: | ||
| 1034 | ; | ||
| 1035 | ; place 32 bit memory board diagnostic byte address into page table | ||
| 1036 | ; xxxx0000h - xxxxFFFFh physical | ||
| 1037 | ; -> 01000000h - 0100FFFFh linear => 64k => 16 entries in page tables | ||
| 1038 | ; => 1st 64k in 5th page table | ||
| 1039 | ; | ||
| 1040 | ; entry: DS pts to DGROUP | ||
| 1041 | ; ES:0 Page table seg. | ||
| 1042 | ; | ||
| 1043 | ; exit: nothing | ||
| 1044 | ; | ||
| 1045 | ; used: ax,di,dx,bx,cx,flags | ||
| 1046 | ; | ||
| 1047 | ; stack: | ||
| 1048 | ; | ||
| 1049 | ;****************************************************************************** | ||
| 1050 | ; | ||
| 1051 | OEM_Init_Diag_Page proc near | ||
| 1052 | assume cs:LAST, ds:dgroup, es:NOTHING | ||
| 1053 | ; | ||
| 1054 | ; | ||
| 1055 | mov di,4*P_SIZE ; ES:DI -> 1st 64k of 5th page table | ||
| 1056 | mov dx,OEM_MEM_HI | ||
| 1057 | xor ax,ax ; start with physical addr = xxxx0000h | ||
| 1058 | mov bh,0 | ||
| 1059 | mov bl,P_AVAIL ; make pages available to all | ||
| 1060 | mov cx,10h ; set 64k worth of entries | ||
| 1061 | IT_set_entry: | ||
| 1062 | call SetPageEntry | ||
| 1063 | ; ES:[DI] pts to next page table entry | ||
| 1064 | add ax,1000h ; next physical page | ||
| 1065 | adc dx,0h ; address in DX,AX | ||
| 1066 | loop IT_set_entry ;Q: done with page table entries ? | ||
| 1067 | ; N: loop again | ||
| 1068 | ; Y: all done | ||
| 1069 | ret | ||
| 1070 | ; | ||
| 1071 | OEM_Init_Diag_Page endp | ||
| 1072 | |||
| 1073 | LAST ends ; End of segment | ||
| 1074 | |||
| 1075 | ifndef NOHIMEM ; if high memory in this model | ||
| 1076 | |||
| 1077 | R_CODE SEGMENT | ||
| 1078 | assume cs:R_CODE, ds:DGROUP, es:DGROUP | ||
| 1079 | |||
| 1080 | ;****************************************************************************** | ||
| 1081 | ; InitLock - Init state of Table lock | ||
| 1082 | ; | ||
| 1083 | ; NOTE: this is a FAR routine. | ||
| 1084 | ; | ||
| 1085 | ; ENTRY: REAL MODE | ||
| 1086 | ; DS = DGROUP | ||
| 1087 | ; | ||
| 1088 | ; EXIT: REAL MODE | ||
| 1089 | ; DGROUP:[DiagByte] = updated to current LOCK state | ||
| 1090 | ; | ||
| 1091 | ; USED: AX,BX | ||
| 1092 | ; | ||
| 1093 | ;****************************************************************************** | ||
| 1094 | InitLOCK proc far | ||
| 1095 | |||
| 1096 | mov [DiagByte],LOW LOCK_ROM ; default is locked | ||
| 1097 | push es | ||
| 1098 | mov ax,X_HI_MEM_SEG | ||
| 1099 | mov es,ax ; ES -> ROM | ||
| 1100 | mov bx,X_MT_386 ; ES:BX -> machine type byte | ||
| 1101 | mov ax,ES:[bx] ; AX = ROM contents | ||
| 1102 | xor ES:[bx],0FFFFh ; flip all bits in ROM | ||
| 1103 | xor ax,0FFFFh ; AX = "flipped" value | ||
| 1104 | cmp ax,ES:[bx] ;Q: flipped value in ROM ? | ||
| 1105 | jne gv_locked ; N: "ROM" is locked | ||
| 1106 | mov [DiagByte],LOW UNLOCK_ROM ;Y: ROM is UNLOCKED | ||
| 1107 | gv_locked: | ||
| 1108 | xor ES:[bx],0FFFFh ; restore ROM contents (if changed) | ||
| 1109 | ; | ||
| 1110 | pop es | ||
| 1111 | ret | ||
| 1112 | |||
| 1113 | InitLOCK endp | ||
| 1114 | |||
| 1115 | R_CODE ENDS | ||
| 1116 | |||
| 1117 | endif ; end of code for not NOHIMEM | ||
| 1118 | |||
| 1119 | end ; of module | ||
| 1120 | |||
diff --git a/v4.0/src/MEMM/MEMM/PAGE.INC b/v4.0/src/MEMM/MEMM/PAGE.INC new file mode 100644 index 0000000..aa76e69 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PAGE.INC | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: PAGE.INC - Definitions for paging on 386 | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ; | ||
| 29 | ; Functional Description: | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ifndef INC_LIST | ||
| 33 | .xlist | ||
| 34 | endif | ||
| 35 | |||
| 36 | P_SIZE equ 1000h ; page size | ||
| 37 | |||
| 38 | P_PRES equ 01h ; page present bit | ||
| 39 | P_WRITE equ 02h ; write access bit | ||
| 40 | P_USER equ 04h ; access bit for User mode | ||
| 41 | P_ACC equ 10h ; page accessed bit | ||
| 42 | P_DIRTY equ 20h ; page dirty bit | ||
| 43 | |||
| 44 | |||
| 45 | P_AVAIL equ (P_PRES+P_WRITE+P_USER) ; avail to everyone & present | ||
| 46 | |||
| 47 | PAGE_ENTRY macro addr,stat | ||
| 48 | dd addr ; access & status in low 12 | ||
| 49 | ; address in high 20 | ||
| 50 | endm | ||
| 51 | |||
| 52 | .list ; end of PAGE.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/PIC_DEF.EQU b/v4.0/src/MEMM/MEMM/PIC_DEF.EQU new file mode 100644 index 0000000..93706b5 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PIC_DEF.EQU | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: PIC_DEF.EQU - 8259 programmable interrupt controllers | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: January 31, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 01/31/86 Original | ||
| 24 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 25 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 26 | ; | ||
| 27 | ;****************************************************************************** | ||
| 28 | ifndef INC_LIST | ||
| 29 | .xlist | ||
| 30 | endif | ||
| 31 | ; | ||
| 32 | ; Master interrupt controller parameters | ||
| 33 | ; | ||
| 34 | PIC1_CMD = 20H ; 8259A command register. | ||
| 35 | PIC1_INIT = 21H ; 8259A initialization register. | ||
| 36 | PIC1_STAT = 20H ; 8259A status (who interrupted) | ||
| 37 | PIC1_MASK = 21H ; 8259A operation control word #1. | ||
| 38 | ; | ||
| 39 | PIC1_ICW1_VAL = 11H ; Edge trig, 8 interval, cascade, ICW4. | ||
| 40 | PIC1_ICW2_VAL = 08H ; Interrupt vector address. | ||
| 41 | PIC1_ICW3_VAL = 04H ; Slave id. | ||
| 42 | PIC1_ICW4_VAL = 01H ; 8088 mode, norm EOI, non-buf, no nest. | ||
| 43 | ; | ||
| 44 | ; Slave interrupt controller parameters | ||
| 45 | ; | ||
| 46 | PIC2_CMD = 0A0H ; 8259A command register. | ||
| 47 | PIC2_INIT = 0A1H ; 8259A initialization register. | ||
| 48 | PIC2_STAT = 0A0H ; 8259A status (who interrupted) | ||
| 49 | PIC2_MASK = 0A1H ; 8259A operation control word #1. | ||
| 50 | ; | ||
| 51 | PIC2_ICW1_VAL = 11H ; Edge trig, 8 interval, cascade, ICW4. | ||
| 52 | PIC2_ICW2_VAL = 70H ; Interrupt vector address. | ||
| 53 | PIC2_ICW3_VAL = 02H ; Master id. | ||
| 54 | PIC2_ICW4_VAL = 01H ; 8088 mode, norm EOI, non-buf, no nest. | ||
| 55 | ; | ||
| 56 | MASK_DISABLE = 0FFH ; Mask register, no levels allowed. | ||
| 57 | READ_ISR = 0BH ; Command to read PIC In-Service-Reg. | ||
| 58 | EOI = 20H ; End-Of-Interrupt (non-specific). | ||
| 59 | ; | ||
| 60 | IRQ0_ENABLE = 11111110B ; Mask to enable IRQ0. | ||
| 61 | IRQ1_ENABLE = 11111101B ; Mask to enable IRQ1. | ||
| 62 | IRQ2_ENABLE = 11111011B ; Mask to enable IRQ2. | ||
| 63 | IRQ3_ENABLE = 11110111B ; Mask to enable IRQ3. | ||
| 64 | IRQ4_ENABLE = 11101111B ; Mask to enable IRQ4. | ||
| 65 | IRQ5_ENABLE = 11011111B ; Mask to enable IRQ5. | ||
| 66 | IRQ6_ENABLE = 10111111B ; Mask to enable IRQ6. | ||
| 67 | IRQ7_ENABLE = 01111110B ; Mask to enable IRQ7. | ||
| 68 | ; | ||
| 69 | IRQ8_ENABLE = 11111110B ; Mask to enable IRQ8. | ||
| 70 | IRQ9_ENABLE = 11111101B ; Mask to enable IRQ9. | ||
| 71 | IRQ10_ENABLE = 11111011B ; Mask to enable IRQ10. | ||
| 72 | IRQ11_ENABLE = 11110111B ; Mask to enable IRQ11. | ||
| 73 | IRQ12_ENABLE = 11101111B ; Mask to enable IRQ12. | ||
| 74 | IRQ13_ENABLE = 11011111B ; Mask to enable IRQ13. | ||
| 75 | IRQ14_ENABLE = 10111111B ; Mask to enable IRQ14. | ||
| 76 | IRQ15_ENABLE = 01111111B ; Mask to enable IRQ15. | ||
| 77 | ; | ||
| 78 | .list ; end of PIC_DEF.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/PPAGE.ASM b/v4.0/src/MEMM/MEMM/PPAGE.ASM new file mode 100644 index 0000000..677c583 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PPAGE.ASM | |||
| @@ -0,0 +1,510 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE PPAGE - MODULE to find mappable Physical pages | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: PPAGE - Find Mappable Physical Pages | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Aug 1, 1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP | ||
| 19 | ; COMMENTS** This routine needs extensive work to do a better | ||
| 20 | ; job of identification of unmappable segments. That | ||
| 21 | ; is why we seem to have a whole lot of procedures | ||
| 22 | ; which don't do much now. | ||
| 23 | ;****************************************************************************** | ||
| 24 | ; | ||
| 25 | ; Change Log: | ||
| 26 | ; | ||
| 27 | ; DATE REVISION Description | ||
| 28 | ; -------- -------- -------------------------------------------- | ||
| 29 | ;****************************************************************************** | ||
| 30 | ; Functional Description: | ||
| 31 | ; This module initialises the mappable physical pages in memory. | ||
| 32 | ; It also finds a valid page frame for use. | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | .lfcond | ||
| 36 | .386p | ||
| 37 | |||
| 38 | page | ||
| 39 | ;****************************************************************************** | ||
| 40 | ; P U B L I C D E C L A R A T I O N S | ||
| 41 | ;****************************************************************************** | ||
| 42 | |||
| 43 | public mappable_segs | ||
| 44 | public Map_tbl | ||
| 45 | public max_PF | ||
| 46 | public find_phys_pages | ||
| 47 | public exclude_segments | ||
| 48 | public is_page_mappable | ||
| 49 | |||
| 50 | page | ||
| 51 | ;****************************************************************************** | ||
| 52 | ; L O C A L C O N S T A N T S | ||
| 53 | ;****************************************************************************** | ||
| 54 | ; | ||
| 55 | FIRST_SYSTEM_ROM_SEG_HI = 0F000h | ||
| 56 | FIRST_SYSTEM_ROM_SEG_LO = 0E000h | ||
| 57 | LAST_SYSTEM_ROM_SEG = 0FFFFh | ||
| 58 | ; | ||
| 59 | FIRST_VIDEO_MEM_SEG = 0A000h | ||
| 60 | LAST_VIDEO_MEM_SEG = 0BFFFh | ||
| 61 | ; | ||
| 62 | FIRST_CONV_UMAP_SEG = 00000h | ||
| 63 | LAST_CONV_UMAP_SEG = 03FFFh | ||
| 64 | |||
| 65 | |||
| 66 | ;****************************************************************************** | ||
| 67 | ; INCLUDE FILES | ||
| 68 | ;****************************************************************************** | ||
| 69 | include vdmseg.inc ; segment definitions | ||
| 70 | include emm386.inc ;contains the error messages | ||
| 71 | include emmdef.inc ;contains some emm defines | ||
| 72 | |||
| 73 | page | ||
| 74 | ;****************************************************************************** | ||
| 75 | ; E X T E R N A L R E F E R E N C E S | ||
| 76 | ;****************************************************************************** | ||
| 77 | ; | ||
| 78 | ; | ||
| 79 | _DATA segment | ||
| 80 | |||
| 81 | extrn PF_Base:word | ||
| 82 | extrn msg_flag:word | ||
| 83 | |||
| 84 | _DATA ends | ||
| 85 | |||
| 86 | ; | ||
| 87 | LAST segment | ||
| 88 | ; | ||
| 89 | extrn rom_srch:near | ||
| 90 | ; | ||
| 91 | LAST ends | ||
| 92 | |||
| 93 | page | ||
| 94 | ;****************************************************************************** | ||
| 95 | ; S E G M E N T D E F I N I T I O N | ||
| 96 | ;****************************************************************************** | ||
| 97 | |||
| 98 | |||
| 99 | ;****************************************************************************** | ||
| 100 | ; | ||
| 101 | ; Code Segments | ||
| 102 | ; | ||
| 103 | ;****************************************************************************** | ||
| 104 | ; | ||
| 105 | _TEXT segment | ||
| 106 | _TEXT ends | ||
| 107 | |||
| 108 | LAST segment | ||
| 109 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 110 | |||
| 111 | page | ||
| 112 | ;************************************************************************* | ||
| 113 | ; | ||
| 114 | ; initialisation data | ||
| 115 | ; | ||
| 116 | ;************************************************************************* | ||
| 117 | ; table for identifying mappable pages | ||
| 118 | ; | ||
| 119 | mappable_segs label byte | ||
| 120 | db TOT_PHYS_PAGES dup(PAGE_MAPPABLE) ; | ||
| 121 | ; | ||
| 122 | ; table for PF base addresses | ||
| 123 | ; | ||
| 124 | Map_tbl label word | ||
| 125 | dw 0c000h | ||
| 126 | dw 0c400h | ||
| 127 | dw 0c800h | ||
| 128 | dw 0cc00h | ||
| 129 | dw 0d000h | ||
| 130 | dw 0d400h | ||
| 131 | dw 0d800h | ||
| 132 | dw 0dc00h | ||
| 133 | max_PF equ (this byte - Map_tbl) | ||
| 134 | dw 0e000h | ||
| 135 | |||
| 136 | page | ||
| 137 | ;****************************************************************************** | ||
| 138 | ; find_phys_pages: routine to find mappable phsyical pages and a page fr | ||
| 139 | ; | ||
| 140 | ; ENTRY: PF_base set to -1 (user didn't specify apge frame) | ||
| 141 | ; or offset into Map_tbl | ||
| 142 | ; EXIT: mappable_segs array initalised to indicate mappable pages | ||
| 143 | ; first_system_page initialised | ||
| 144 | ; num_system_pages initialised | ||
| 145 | ; PF_Base initalised to page frame | ||
| 146 | ; [msg_flag] set if error to error message number | ||
| 147 | ; USED: none | ||
| 148 | ; | ||
| 149 | ;****************************************************************************** | ||
| 150 | find_phys_pages proc near | ||
| 151 | ; | ||
| 152 | ; start out with all the pages initialised to be mappable except those excluded | ||
| 153 | ; by explicit instruction of the command line. | ||
| 154 | ; | ||
| 155 | |||
| 156 | ; | ||
| 157 | ; exclude segments in the lo end of system memory | ||
| 158 | ; | ||
| 159 | call exclude_conv_RAM | ||
| 160 | |||
| 161 | ; exclude segments in the system ROM area | ||
| 162 | ; | ||
| 163 | call exclude_system_ROM | ||
| 164 | |||
| 165 | ; | ||
| 166 | ; exclude segments in the video area | ||
| 167 | ; | ||
| 168 | call exclude_video_mem | ||
| 169 | |||
| 170 | ; | ||
| 171 | ; then search for option rom's in the area C000 to E000 and exclude the | ||
| 172 | ; segments in which option rom exists. | ||
| 173 | ; | ||
| 174 | call rom_srch ; this searches for option rom's and | ||
| 175 | ; removes the segments of these from | ||
| 176 | ; being mappable | ||
| 177 | ; | ||
| 178 | ; then find the page frame from the information of mappable segs from C000-E000 | ||
| 179 | ; and the user specified page frame (if any). | ||
| 180 | ; | ||
| 181 | call find_pf_base | ||
| 182 | ; | ||
| 183 | ; and then exit | ||
| 184 | ; | ||
| 185 | ret | ||
| 186 | ; | ||
| 187 | find_phys_pages endp | ||
| 188 | |||
| 189 | page | ||
| 190 | ;****************************************************************************** | ||
| 191 | ; find_pf_base: routine to find a valid page frame | ||
| 192 | ; | ||
| 193 | ; ENTRY: PF_base set to -1 (user didn't specify apge frame) | ||
| 194 | ; or index into Map_tbl | ||
| 195 | ; ax = index into Map_tbl from rom_srch on a possible pageframe. | ||
| 196 | ; | ||
| 197 | ; EXIT: PF_base set to page frame segment (C000..E000) on no error | ||
| 198 | ; If error msg_flag set to appropriate error message | ||
| 199 | ; | ||
| 200 | ; USES: NONE | ||
| 201 | ; | ||
| 202 | ;****************************************************************************** | ||
| 203 | find_pf_base proc near | ||
| 204 | ; | ||
| 205 | push ax | ||
| 206 | push bx | ||
| 207 | push cx | ||
| 208 | push si | ||
| 209 | ; | ||
| 210 | ; we have to examine all the possible page frames by looking at the entries | ||
| 211 | ; for the page frame in the mappable_segs array and find all possible page | ||
| 212 | ; frames. the first such valid page frame found is remembered | ||
| 213 | ; | ||
| 214 | |||
| 215 | ; | ||
| 216 | ; initialise | ||
| 217 | ; | ||
| 218 | mov ax,0ffffh ; first possible page frame | ||
| 219 | xor bx,bx ; index into map_tbl | ||
| 220 | ; | ||
| 221 | ; outer loop entry. check for loop termination | ||
| 222 | ; | ||
| 223 | examine_map_tbl_loop: | ||
| 224 | ; | ||
| 225 | cmp bx,MAX_PF ; are we done | ||
| 226 | ja choose_PF ; yes, go to choose page frame | ||
| 227 | ; | ||
| 228 | ; get the page frame segment. convert to phys. page # | ||
| 229 | ; | ||
| 230 | mov si,cs:Map_Tbl[bx] ; | ||
| 231 | shr si,10 | ||
| 232 | ; | ||
| 233 | ; examine the entries for the 4 pages comprising this segment | ||
| 234 | ; | ||
| 235 | mov cx,4 | ||
| 236 | check_pages_loop: | ||
| 237 | cmp cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 238 | jne invalidate_PF | ||
| 239 | inc si | ||
| 240 | loop check_pages_loop | ||
| 241 | |||
| 242 | ;***SUCCESS | ||
| 243 | |||
| 244 | ; | ||
| 245 | ; exit point. pf is valid. see if we already have a pf. if not we store | ||
| 246 | ; this. | ||
| 247 | ; | ||
| 248 | cmp ax,0ffffh ; do we have a pf already? | ||
| 249 | jne skip_get_PF ; skip if we do | ||
| 250 | mov ax,bx ; else store | ||
| 251 | skip_get_PF: | ||
| 252 | ; | ||
| 253 | ; go to examine next PF | ||
| 254 | ; | ||
| 255 | jmp next_PF | ||
| 256 | |||
| 257 | ;***FAILURE | ||
| 258 | |||
| 259 | ; | ||
| 260 | ; exit point. pf is invalid. remove it from map_tbl | ||
| 261 | ; | ||
| 262 | invalidate_PF: | ||
| 263 | mov cs:Map_Tbl[bx],0ffffh ; | ||
| 264 | ; | ||
| 265 | ;***SETUP TO LOOP AGAIN | ||
| 266 | next_PF: | ||
| 267 | ; | ||
| 268 | add bx,2 | ||
| 269 | jmp examine_map_tbl_loop | ||
| 270 | ; | ||
| 271 | choose_PF: | ||
| 272 | ; | ||
| 273 | ; Choosing a page frame. If the user has specified a page frame then | ||
| 274 | ; validate it else give him the page frame we found first. | ||
| 275 | ; | ||
| 276 | ; | ||
| 277 | ; has the user specified a pf. if so go to validate it | ||
| 278 | ; | ||
| 279 | cmp [PF_Base],0ffffh ; | ||
| 280 | jne def_cont2 | ||
| 281 | ; | ||
| 282 | ; user didn't specify a pf. did we find a pf. if so give it else indicate | ||
| 283 | ; error | ||
| 284 | ; | ||
| 285 | cmp ax,0ffffh ; did we find one | ||
| 286 | je no_PF_warn ; if not go to warn the user | ||
| 287 | mov bx,ax | ||
| 288 | mov ax, cs:Map_Tbl[bx] ; get the PF | ||
| 289 | mov [PF_Base],ax ; | ||
| 290 | or [msg_flag],BASE_ADJ_MSG ; | ||
| 291 | jmp pf_xit | ||
| 292 | |||
| 293 | ; | ||
| 294 | ; we don't have a pf. warn the user | ||
| 295 | ; | ||
| 296 | no_PF_warn: | ||
| 297 | or [msg_flag],NO_PF_MSG | ||
| 298 | jmp pf_xit | ||
| 299 | ; | ||
| 300 | ; they specified a base address. Let's make sure it's good | ||
| 301 | ; | ||
| 302 | def_cont2: | ||
| 303 | mov bx,[PF_Base] ; get the offset they specified | ||
| 304 | mov ax,bx ; ax = bx | ||
| 305 | shr ax,1 ; back to 0..8 | ||
| 306 | mov cx,0400h ; length of PF segments | ||
| 307 | mul cx ; addr = 0c000h + (Mx-1)*400h | ||
| 308 | add ax,0c000h | ||
| 309 | mov [PF_Base],ax ; save it | ||
| 310 | |||
| 311 | cmp cs:Map_tbl[bx],0ffffh ; Is this any good? | ||
| 312 | jne pf_xit ; probably | ||
| 313 | or [msg_flag],PF_WARN_MSG ; probably not | ||
| 314 | ; | ||
| 315 | ; we need to ensure that the pages corresponding to the page frame are forced | ||
| 316 | ; into being mappable. this is necessary because we accept the user's discretio | ||
| 317 | ; in forcing a page frame in a certain area. | ||
| 318 | ; | ||
| 319 | mov si,ax ; segment | ||
| 320 | shr si,10 ; phys page# | ||
| 321 | mov cx,4 | ||
| 322 | force_PF_pages: | ||
| 323 | mov cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 324 | inc si | ||
| 325 | loop force_PF_pages | ||
| 326 | |||
| 327 | pf_xit: | ||
| 328 | pop si | ||
| 329 | pop cx | ||
| 330 | pop bx | ||
| 331 | pop ax | ||
| 332 | ret | ||
| 333 | |||
| 334 | find_pf_base endp | ||
| 335 | |||
| 336 | |||
| 337 | ;***********************************************************************; | ||
| 338 | ; exclude_video_mem ; | ||
| 339 | ; ; | ||
| 340 | ; Excludes the segments between A000 and C000. ; | ||
| 341 | ; ; | ||
| 342 | ; input: none ; | ||
| 343 | ; ; | ||
| 344 | ; returns: none ; | ||
| 345 | ; ; | ||
| 346 | ; uses: ; | ||
| 347 | ; ; | ||
| 348 | ; calls:exclude_segments ; | ||
| 349 | ; ; | ||
| 350 | ; History: ; | ||
| 351 | ; ISP (isp). Wrote it. ; | ||
| 352 | ;***********************************************************************; | ||
| 353 | exclude_video_mem proc near | ||
| 354 | ; | ||
| 355 | push bx | ||
| 356 | push ax | ||
| 357 | ; | ||
| 358 | mov bx,FIRST_VIDEO_MEM_SEG | ||
| 359 | mov ax,LAST_VIDEO_MEM_SEG | ||
| 360 | call exclude_segments | ||
| 361 | ; | ||
| 362 | pop ax | ||
| 363 | pop bx | ||
| 364 | ret | ||
| 365 | ; | ||
| 366 | exclude_video_mem endp | ||
| 367 | |||
| 368 | ;***********************************************************************; | ||
| 369 | ; exclude_system_ROM ; | ||
| 370 | ; ; | ||
| 371 | ; Excludes the segments between A000 and C000. ; | ||
| 372 | ; ; | ||
| 373 | ; input: none ; | ||
| 374 | ; ; | ||
| 375 | ; returns: none ; | ||
| 376 | ; ; | ||
| 377 | ; uses: ; | ||
| 378 | ; ; | ||
| 379 | ; calls:exclude_segments ; | ||
| 380 | ; ; | ||
| 381 | ; History: ; | ||
| 382 | ; ISP (isp). Wrote it. ; | ||
| 383 | ;***********************************************************************; | ||
| 384 | exclude_system_ROM proc near | ||
| 385 | ; | ||
| 386 | push bx | ||
| 387 | push ax | ||
| 388 | ; | ||
| 389 | ifndef NOHIMEM | ||
| 390 | mov bx,FIRST_SYSTEM_ROM_SEG_LO | ||
| 391 | else | ||
| 392 | mov bx,FIRST_SYSTEM_ROM_SEG_HI | ||
| 393 | endif | ||
| 394 | |||
| 395 | mov ax,LAST_SYSTEM_ROM_SEG | ||
| 396 | call exclude_segments | ||
| 397 | ; | ||
| 398 | pop ax | ||
| 399 | pop bx | ||
| 400 | ret | ||
| 401 | ; | ||
| 402 | exclude_system_ROM endp | ||
| 403 | |||
| 404 | ;***********************************************************************; | ||
| 405 | ; exclude_conv_RAM ; | ||
| 406 | ; ; | ||
| 407 | ; Excludes segments between 0000 and 4000h ; | ||
| 408 | ; ; | ||
| 409 | ; inputs:none ; | ||
| 410 | ; ; | ||
| 411 | ; returns: none ; | ||
| 412 | ; ; | ||
| 413 | ; History: ; | ||
| 414 | ; ISP (isp). Wrote it | ||
| 415 | ;***********************************************************************; | ||
| 416 | exclude_conv_RAM proc near | ||
| 417 | ; | ||
| 418 | push bx | ||
| 419 | push ax | ||
| 420 | ; | ||
| 421 | mov bx,FIRST_CONV_UMAP_SEG | ||
| 422 | mov ax,LAST_CONV_UMAP_SEG | ||
| 423 | call exclude_segments | ||
| 424 | ; | ||
| 425 | pop ax | ||
| 426 | pop bx | ||
| 427 | ret | ||
| 428 | ; | ||
| 429 | exclude_conv_RAM endp | ||
| 430 | |||
| 431 | ;-----------------------------------------------------------------------; | ||
| 432 | ; exclude_segments ; | ||
| 433 | ; ; | ||
| 434 | ; Excludes the given segments from the memory map. ; | ||
| 435 | ; ; | ||
| 436 | ; Arguments: ; | ||
| 437 | ; AX = high segment ; | ||
| 438 | ; BX = low segment ; | ||
| 439 | ; Returns: ; | ||
| 440 | ; nothing ; | ||
| 441 | ; Alters: ; | ||
| 442 | ; AX,BX ; | ||
| 443 | ; Calls: ; | ||
| 444 | ; nothing ; | ||
| 445 | ; History: ; | ||
| 446 | ; ISP (isp). modified from ps2emm sources. ; | ||
| 447 | ;-----------------------------------------------------------------------; | ||
| 448 | exclude_segments proc near | ||
| 449 | ; | ||
| 450 | push cx | ||
| 451 | push es | ||
| 452 | push di | ||
| 453 | ; | ||
| 454 | ; fix the segments to form physical page numbers | ||
| 455 | ; | ||
| 456 | mov cl,10 ; to convert segment to physical page # | ||
| 457 | shr ax,cl | ||
| 458 | shr bx,cl | ||
| 459 | sub ax,bx | ||
| 460 | jb exclude_segments_done | ||
| 461 | inc ax | ||
| 462 | mov cx,ax | ||
| 463 | ; | ||
| 464 | ; get addressing into mappable_segs array | ||
| 465 | ; | ||
| 466 | push cs | ||
| 467 | pop es | ||
| 468 | assume es:nothing | ||
| 469 | lea di, mappable_segs[bx] | ||
| 470 | mov al,PAGE_NOT_MAPPABLE | ||
| 471 | cld | ||
| 472 | rep stosb | ||
| 473 | exclude_segments_done: | ||
| 474 | ; | ||
| 475 | pop di | ||
| 476 | pop es | ||
| 477 | pop cx | ||
| 478 | ret | ||
| 479 | ; | ||
| 480 | exclude_segments endp | ||
| 481 | |||
| 482 | ;-----------------------------------------------------------------------; | ||
| 483 | ; is_page_mappable ; | ||
| 484 | ; ; | ||
| 485 | ; specifies whether a given physical page is mappable or not. ; | ||
| 486 | ; ; | ||
| 487 | ; Arguments: ; | ||
| 488 | ; si = physical page ; | ||
| 489 | ; Returns: ; | ||
| 490 | ; ZF set if mappable ; | ||
| 491 | ; ZF clear if not mappable ; | ||
| 492 | ; Alters: ; | ||
| 493 | ; flags ; | ||
| 494 | ; Calls: ; | ||
| 495 | ; nothing ; | ||
| 496 | ; History: ; | ||
| 497 | ; ISP (isp). 8/29/88 ; | ||
| 498 | ;-----------------------------------------------------------------------; | ||
| 499 | is_page_mappable proc near | ||
| 500 | ; | ||
| 501 | cmp cs:mappable_segs[si],PAGE_MAPPABLE | ||
| 502 | ret | ||
| 503 | ; | ||
| 504 | is_page_mappable endp | ||
| 505 | |||
| 506 | LAST ends ; End of segment | ||
| 507 | ; | ||
| 508 | |||
| 509 | end ; End of module | ||
| 510 | |||
diff --git a/v4.0/src/MEMM/MEMM/PRINT.ASM b/v4.0/src/MEMM/MEMM/PRINT.ASM new file mode 100644 index 0000000..91d8571 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/PRINT.ASM | |||
| @@ -0,0 +1,424 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title PRINT.ASM - Protected Mode Print Routines | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMMD.EXE - MICROSOFT Expanded Memory Manager 386 DEBUG Driver | ||
| 11 | ; | ||
| 12 | ; Module: PRINT.ASM - Protected Mode Print Routines | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 29 | ; 07/05/86 0.04 Moved to DCODE segment | ||
| 30 | ; 07/06/86 0.04 moved data to DDATA segment | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | .lfcond ; list false conditionals | ||
| 38 | .386p | ||
| 39 | |||
| 40 | public PrintString | ||
| 41 | public PrintHex | ||
| 42 | public kputc | ||
| 43 | public RowCol | ||
| 44 | public IsReal | ||
| 45 | |||
| 46 | NAME print | ||
| 47 | |||
| 48 | ;** print - cga simple print routines | ||
| 49 | ; | ||
| 50 | include VDMseg.inc | ||
| 51 | include VDMsel.inc | ||
| 52 | include desc.inc | ||
| 53 | |||
| 54 | ;*** IsReal - determine mode of cpu | ||
| 55 | ; | ||
| 56 | ; This routine is useful when writing dual mode code. | ||
| 57 | ; It returns with 'Z' = 1 if the cpu is in real mode, | ||
| 58 | ; otherwise 'Z' = 0. | ||
| 59 | ; | ||
| 60 | ; ENTRY DUAL MODE | ||
| 61 | ; | ||
| 62 | ; EXIT 'Z' = 1 (protected mode), 0 (real mode) | ||
| 63 | ; | ||
| 64 | ; USES flags | ||
| 65 | ; | ||
| 66 | _TEXT segment | ||
| 67 | |||
| 68 | assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing | ||
| 69 | |||
| 70 | IsReal proc near | ||
| 71 | |||
| 72 | push ax | ||
| 73 | smsw ax | ||
| 74 | xor al, 0ffh | ||
| 75 | and al, 1 | ||
| 76 | pop ax | ||
| 77 | ret ; returns with flags set | ||
| 78 | |||
| 79 | IsReal endp | ||
| 80 | |||
| 81 | _TEXT ends | ||
| 82 | |||
| 83 | ;*** kputc - write character/attribute to screen | ||
| 84 | ; | ||
| 85 | ; This is a simple character output routine. It does not | ||
| 86 | ; interleave writes to video memory with the 6845. It | ||
| 87 | ; does not update the cursor position. It does not understand | ||
| 88 | ; anything except a CGA in 80x25 text mode. | ||
| 89 | ; | ||
| 90 | ; ENTRY PROTECTED MODE | ||
| 91 | ; AX - character-attribute to write | ||
| 92 | ; DS - kernel data selector | ||
| 93 | ; | ||
| 94 | ; EXIT none - character written | ||
| 95 | ; | ||
| 96 | ; USES AX, flags | ||
| 97 | ; | ||
| 98 | |||
| 99 | _DATA segment | ||
| 100 | RowCol dw 0 | ||
| 101 | _DATA ends | ||
| 102 | |||
| 103 | CR equ 0dh ; carriage return | ||
| 104 | LF equ 0ah ; line feed | ||
| 105 | TAB equ 9 ; tab | ||
| 106 | BS equ 8 ; backspace | ||
| 107 | |||
| 108 | COLOUR_PARA equ 0b800h | ||
| 109 | |||
| 110 | _TEXT segment | ||
| 111 | |||
| 112 | assume cs:_TEXT, ds:_DATA, es:nothing, ss:nothing | ||
| 113 | |||
| 114 | kputc proc far | ||
| 115 | |||
| 116 | push bx ; save callers regs | ||
| 117 | push cx | ||
| 118 | push dx | ||
| 119 | push si | ||
| 120 | push di | ||
| 121 | push es | ||
| 122 | push ds | ||
| 123 | |||
| 124 | call IsReal ; need dual mode access | ||
| 125 | jnz kp10 | ||
| 126 | mov dx, VDMD_GSEL ; selector for protected mode | ||
| 127 | jmp kp11 | ||
| 128 | kp10: | ||
| 129 | mov dx, seg _DATA ; para for real mode | ||
| 130 | kp11: | ||
| 131 | push dx ; save this segment for later | ||
| 132 | |||
| 133 | mov ds, dx ; DS -> data segment | ||
| 134 | mov dx, ds:[RowCol] ; DX = current row/col | ||
| 135 | |||
| 136 | cmp al, CR ; is character a CR? | ||
| 137 | jne kp1 | ||
| 138 | |||
| 139 | mov dl, 0 ; yes, go to column 0 | ||
| 140 | jmp kp3 ; jump to common code | ||
| 141 | kp1: | ||
| 142 | |||
| 143 | cmp al, LF ; is character a LF? | ||
| 144 | jne kp2 | ||
| 145 | |||
| 146 | inc dh ; yes, go to next row | ||
| 147 | jmp kp3 ; jump to common code | ||
| 148 | kp2: | ||
| 149 | |||
| 150 | cmp al, TAB ; is it a tab | ||
| 151 | jne kp12 | ||
| 152 | and dl, 0f8h ; mask off low 3 bits (8 ch) | ||
| 153 | add dl, 8 ; move to next tab position | ||
| 154 | jmp kp3 ; jmp to common code | ||
| 155 | kp12: | ||
| 156 | |||
| 157 | cmp al, BS ; is it backspace | ||
| 158 | jne kp13 | ||
| 159 | dec dl ; back up one column | ||
| 160 | jmp kp3 ; goto common code | ||
| 161 | kp13: | ||
| 162 | ; Must be ordinary character. Write it to screen, update position | ||
| 163 | |||
| 164 | push ax ; save char/attr | ||
| 165 | |||
| 166 | mov al, dh ; AL = row | ||
| 167 | mov ah, 80 ; multiplier, 80 char per row | ||
| 168 | mul ah ; AX = cell at start of row | ||
| 169 | mov bh, 0 | ||
| 170 | mov bl, dl ; BX = column | ||
| 171 | add bx, ax ; BX = cell | ||
| 172 | shl bx, 1 ; BX = byte offset of cell | ||
| 173 | |||
| 174 | call IsReal ; bi-modal access to screen | ||
| 175 | jnz kp6 | ||
| 176 | mov ax, COLOUR_GSEL ; screen selector for protected mode | ||
| 177 | jmp kp7 | ||
| 178 | kp6: | ||
| 179 | mov ax, COLOUR_PARA ; screen para for real mode | ||
| 180 | kp7: | ||
| 181 | mov es, ax ; ES -> screen | ||
| 182 | |||
| 183 | pop es:[bx] ; write character | ||
| 184 | inc dl ; update column | ||
| 185 | kp3: | ||
| 186 | ; Common code, first check for line wrap: | ||
| 187 | |||
| 188 | cmp dl, 80 ; beyond rhs of screen? | ||
| 189 | jl kp4 | ||
| 190 | mov dl, 0 ; go to col 0 | ||
| 191 | inc dh ; and move to next line | ||
| 192 | kp4: | ||
| 193 | ; Now check for scroll needed: | ||
| 194 | |||
| 195 | cmp dh, 25 ; are we off end of screen? | ||
| 196 | jl kp5 | ||
| 197 | |||
| 198 | ; Now scroll screen | ||
| 199 | |||
| 200 | call IsReal ; bi-modal access to screen | ||
| 201 | jnz kp8 | ||
| 202 | mov ax, COLOUR_GSEL ; screen selector for protected mode | ||
| 203 | jmp kp9 | ||
| 204 | kp8: | ||
| 205 | mov ax, COLOUR_PARA ; screen para for real mode | ||
| 206 | kp9: | ||
| 207 | mov ds, ax ; DS -> screen | ||
| 208 | mov es, ax ; ES -> screen | ||
| 209 | |||
| 210 | mov di, 0 ; ES:DI = copy destination | ||
| 211 | mov si, 160 ; DS:SI = copy source | ||
| 212 | mov cx, 2000-80 ; copy word count | ||
| 213 | cld | ||
| 214 | rep movsw ; scroll | ||
| 215 | |||
| 216 | ; Blank bottom line | ||
| 217 | |||
| 218 | mov al, ' ' | ||
| 219 | mov ah, 7 ; AX = blank character | ||
| 220 | |||
| 221 | mov cx, 80 ; number of cells to blank | ||
| 222 | mov di, 4000-160 ; ES:DI = start point | ||
| 223 | rep stosw | ||
| 224 | |||
| 225 | ; Update position | ||
| 226 | |||
| 227 | mov dh, 24 ; new row | ||
| 228 | kp5: | ||
| 229 | pop ds ; set DS to data again | ||
| 230 | mov ds:[RowCol], dx ; update row/col | ||
| 231 | |||
| 232 | ; call SetCursor | ||
| 233 | |||
| 234 | pop ds ; restore regs | ||
| 235 | pop es | ||
| 236 | pop di | ||
| 237 | pop si | ||
| 238 | pop dx | ||
| 239 | pop cx | ||
| 240 | pop bx | ||
| 241 | |||
| 242 | ret | ||
| 243 | |||
| 244 | kputc endp | ||
| 245 | _TEXT ends | ||
| 246 | |||
| 247 | |||
| 248 | ;*** SetCursor - updates cursor position | ||
| 249 | ; | ||
| 250 | ; This routine reprograms the 6845 cursor position, and | ||
| 251 | ; stores the new cursor position in the ROM bios data area. | ||
| 252 | ; | ||
| 253 | ; ENTRY DUAL MODE | ||
| 254 | ; DH, DL = row, col | ||
| 255 | ; | ||
| 256 | ; EXIT cursor updated | ||
| 257 | ; | ||
| 258 | ; USES ax, bx, cx, flags | ||
| 259 | ; | ||
| 260 | |||
| 261 | CRT_COLS equ 04ah | ||
| 262 | CURSOR_POSN equ 050h | ||
| 263 | CRT_START equ 04eh | ||
| 264 | ADDR_6845 equ 063h | ||
| 265 | |||
| 266 | _TEXT segment | ||
| 267 | |||
| 268 | assume cs:_TEXT, ds:_DATA, es:nothing, ss:nothing | ||
| 269 | |||
| 270 | SetCursor proc near | ||
| 271 | |||
| 272 | push ds | ||
| 273 | mov bx, 40h | ||
| 274 | mov ds, bx | ||
| 275 | |||
| 276 | ; Save new position in BIOS data area | ||
| 277 | |||
| 278 | mov ds:[CURSOR_POSN], dx | ||
| 279 | |||
| 280 | ; Calculate offset on screen | ||
| 281 | |||
| 282 | mov al, dh ; row | ||
| 283 | mul byte ptr ds:[CRT_COLS] ; row * cols | ||
| 284 | mov bl, dl ; bl = column | ||
| 285 | mov bh, 0 ; bx = column | ||
| 286 | add ax, bx ; ax = offset in screen | ||
| 287 | sal ax, 1 ; double for attribute bytes | ||
| 288 | mov cx, ds:[CRT_START] ; cx = start point of screen | ||
| 289 | add cx, ax ; cx = offset of cursor | ||
| 290 | sar cx, 1 ; convert to char count only | ||
| 291 | |||
| 292 | ; Now program 6845 | ||
| 293 | |||
| 294 | mov al, 14 ; 6845 register | ||
| 295 | mov dx, ds:[ADDR_6845] ; base port # | ||
| 296 | out dx, al | ||
| 297 | inc dx | ||
| 298 | jmp short $+2 | ||
| 299 | |||
| 300 | mov al, ch | ||
| 301 | out dx, al | ||
| 302 | dec dx | ||
| 303 | jmp short $+2 | ||
| 304 | |||
| 305 | mov al, 15 | ||
| 306 | out dx, al | ||
| 307 | inc dx | ||
| 308 | jmp short $+2 | ||
| 309 | |||
| 310 | mov al, cl | ||
| 311 | out dx, al | ||
| 312 | |||
| 313 | pop ds | ||
| 314 | |||
| 315 | ret | ||
| 316 | |||
| 317 | SetCursor endp | ||
| 318 | _TEXT ends | ||
| 319 | |||
| 320 | |||
| 321 | ;*** PrintString - prints a message on console | ||
| 322 | ; | ||
| 323 | ; This routine calls the "kernel" to print a string | ||
| 324 | ; one character at a time. | ||
| 325 | ; | ||
| 326 | ; ENTRY 286 PROTECTED MODE | ||
| 327 | ; DS - DATA3_SEL | ||
| 328 | ; ES - DATA3_SEL | ||
| 329 | ; SI - offset in DS of null terminated string to print | ||
| 330 | ; | ||
| 331 | ; EXIT String printed | ||
| 332 | ; | ||
| 333 | ; USES Flags | ||
| 334 | ; | ||
| 335 | |||
| 336 | _TEXT segment | ||
| 337 | |||
| 338 | assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing | ||
| 339 | |||
| 340 | PrintString proc near | ||
| 341 | |||
| 342 | cld ; set up for string ops | ||
| 343 | push si ; save callers regs | ||
| 344 | push ax | ||
| 345 | |||
| 346 | pr1: ; loop printing until null | ||
| 347 | lodsb ; al = char to print | ||
| 348 | and al, al ; terminator ? | ||
| 349 | je pr2 | ||
| 350 | mov ah, 7 ; attribute | ||
| 351 | |||
| 352 | db 9ah ; far call | ||
| 353 | dw offset _TEXT:kputc ; offset | ||
| 354 | dw VDMC_GSEL ; selector | ||
| 355 | |||
| 356 | jmp pr1 ; back for more | ||
| 357 | pr2: | ||
| 358 | pop ax ; restore callers regs | ||
| 359 | pop si | ||
| 360 | |||
| 361 | ret | ||
| 362 | |||
| 363 | PrintString endp | ||
| 364 | |||
| 365 | _TEXT ends | ||
| 366 | |||
| 367 | ;*** Hex2String | ||
| 368 | ; | ||
| 369 | ; Convert content of AX into 4 Hex digits string at ES:DI | ||
| 370 | ; | ||
| 371 | ; ENTRY AX value to convert | ||
| 372 | ; ES:DI storage string location | ||
| 373 | ; | ||
| 374 | |||
| 375 | _TEXT segment | ||
| 376 | |||
| 377 | assume cs:_TEXT, ds:nothing, es:nothing, ss:nothing | ||
| 378 | |||
| 379 | PutHexChar proc near | ||
| 380 | |||
| 381 | cmp al,9 | ||
| 382 | ja PHC_AF | ||
| 383 | add al,30h | ||
| 384 | jmp PHC_exit | ||
| 385 | PHC_AF: | ||
| 386 | add al,(41h - 0ah) | ||
| 387 | PHC_exit: | ||
| 388 | push ax | ||
| 389 | mov ah,7 | ||
| 390 | db 9ah ; far call | ||
| 391 | dw offset _TEXT:kputc ; offset | ||
| 392 | dw VDMC_GSEL ; selector | ||
| 393 | pop ax | ||
| 394 | ret | ||
| 395 | |||
| 396 | PutHexChar endp | ||
| 397 | |||
| 398 | PrintHex proc near | ||
| 399 | |||
| 400 | cld | ||
| 401 | |||
| 402 | xchg al,ah | ||
| 403 | push ax | ||
| 404 | shr al,4 | ||
| 405 | call PutHexChar | ||
| 406 | pop ax | ||
| 407 | and al,0fh | ||
| 408 | call PutHexChar | ||
| 409 | xchg al,ah | ||
| 410 | push ax | ||
| 411 | shr al,4 | ||
| 412 | call PutHexChar | ||
| 413 | pop ax | ||
| 414 | and al,0fh | ||
| 415 | call PutHexChar | ||
| 416 | |||
| 417 | ret | ||
| 418 | |||
| 419 | PrintHex endp | ||
| 420 | |||
| 421 | _TEXT ends | ||
| 422 | |||
| 423 | end | ||
| 424 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/RETREAL.ASM b/v4.0/src/MEMM/MEMM/RETREAL.ASM new file mode 100644 index 0000000..8ffc602 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/RETREAL.ASM | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title RetReal - Return-To-Real routine(s) for the 386 | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: RetReal - Return-To-Real routine(s) for the 386 | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: February 20, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 02/20/86 Original | ||
| 27 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 28 | ; 06/01/86 Removed Real386a (loadall version) and left only | ||
| 29 | ; RetReal via PE bit | ||
| 30 | ; 06/21/86 0.02 Saved Eax | ||
| 31 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 32 | ; 07/02/86 0.03 Reset TSS busy bit | ||
| 33 | ; 07/05/86 0.04 Added Real_Seg label for _TEXT fixup | ||
| 34 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; This module contains the routine RetReal which goes from Ring 0 protected | ||
| 41 | ; mode to Real Mode by resetting the PE bit (and the PG bit). | ||
| 42 | ; | ||
| 43 | ; NOTE: this module only works on the B0 and later parts. The A2 part | ||
| 44 | ; will leave the CS non writeable. | ||
| 45 | ; | ||
| 46 | ;****************************************************************************** | ||
| 47 | .lfcond ; list false conditionals | ||
| 48 | .386p | ||
| 49 | page | ||
| 50 | ;****************************************************************************** | ||
| 51 | ; P U B L I C D E C L A R A T I O N S | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; | ||
| 54 | public RetReal | ||
| 55 | public Real_Seg | ||
| 56 | |||
| 57 | page | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; I N C L U D E F I L E S | ||
| 60 | ;****************************************************************************** | ||
| 61 | |||
| 62 | include VDMSEG.INC | ||
| 63 | include VDMSEL.INC | ||
| 64 | include INSTR386.INC | ||
| 65 | include OEMDEP.INC | ||
| 66 | |||
| 67 | ; | ||
| 68 | ;****************************************************************************** | ||
| 69 | ; E X T E R N A L R E F E R E N C E S | ||
| 70 | ;****************************************************************************** | ||
| 71 | ; | ||
| 72 | _DATA segment | ||
| 73 | extrn Active_Status:byte | ||
| 74 | _DATA ends | ||
| 75 | |||
| 76 | _TEXT segment | ||
| 77 | |||
| 78 | extrn SelToSeg:near ; selector to segment (I286) | ||
| 79 | extrn DisableA20:near ; disable A20 line (MODESW) | ||
| 80 | |||
| 81 | _TEXT ends | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; L O C A L C O N S T A N T S | ||
| 84 | ;****************************************************************************** | ||
| 85 | ; | ||
| 86 | FALSE equ 0 | ||
| 87 | TRUE equ not FALSE | ||
| 88 | |||
| 89 | page | ||
| 90 | ;****************************************************************************** | ||
| 91 | ; S E G M E N T D E F I N I T I O N | ||
| 92 | ;****************************************************************************** | ||
| 93 | |||
| 94 | _TEXT segment | ||
| 95 | assume cs:_TEXT, ds:DGROUP | ||
| 96 | |||
| 97 | ;*** RetReal - cause a 386 mode switch to real mode | ||
| 98 | ; | ||
| 99 | ; ENTRY Ring 0 protected mode | ||
| 100 | ; CLI - interrupts disabled | ||
| 101 | ; NMI should also be disabled here. | ||
| 102 | ifndef NOHIMEM | ||
| 103 | ; FS = Diag segment selector | ||
| 104 | endif | ||
| 105 | ; | ||
| 106 | ; EXIT Real Mode | ||
| 107 | ; DGROUP:[Active_Status] = 0 | ||
| 108 | ; CS = _TEXT | ||
| 109 | ; DS = ES = FS = GS = DGROUP | ||
| 110 | ; SS = stack segment | ||
| 111 | ; general registers preserved | ||
| 112 | ; flags modified | ||
| 113 | ; interrupts disabled | ||
| 114 | ; A20 disabled | ||
| 115 | ifndef NOHIMEM | ||
| 116 | ; high system memory LOCKED | ||
| 117 | endif | ||
| 118 | ; | ||
| 119 | ; USES see exit conditions above | ||
| 120 | ; | ||
| 121 | ; DESCRIPTION | ||
| 122 | ; | ||
| 123 | real_gdt label qword | ||
| 124 | real_idt dw 0FFFFh ; limit | ||
| 125 | dw 0000 ; base | ||
| 126 | dw 0000 | ||
| 127 | dw 0000 ; just in case | ||
| 128 | |||
| 129 | public RetReal | ||
| 130 | RetReal proc near | ||
| 131 | PUSH_EAX ; save two scratch registers | ||
| 132 | push bx | ||
| 133 | cli ; disable ints | ||
| 134 | |||
| 135 | smsw ax ;check to see if we are in real mode | ||
| 136 | test ax,1 | ||
| 137 | jnz rl386_a ;jump if in protected mode | ||
| 138 | sti | ||
| 139 | pop bx | ||
| 140 | POP_EAX | ||
| 141 | ret ;otherwise return | ||
| 142 | |||
| 143 | rl386_a: | ||
| 144 | |||
| 145 | ; | ||
| 146 | ; reset TSS busy bit before returning to Real Mode | ||
| 147 | ; | ||
| 148 | mov ax, GDTD_GSEL | ||
| 149 | mov es, ax ; ES:0 = ptr to gdt | ||
| 150 | |||
| 151 | and byte ptr ES:[TSS_GSEL + 5], 11111101B | ||
| 152 | |||
| 153 | ; | ||
| 154 | ; lock high system ROM before returning to real | ||
| 155 | ; | ||
| 156 | HwTabLock | ||
| 157 | |||
| 158 | ; | ||
| 159 | ; First save return ss:sp. We have to translate | ||
| 160 | ; the current ss (a selector) into a segment number. | ||
| 161 | ; Calculate a real mode segment corresponding to the | ||
| 162 | ; current protected mode stack selector base address. | ||
| 163 | ; | ||
| 164 | ; We get the base address from the descriptor table, | ||
| 165 | ; and convert it to a paragraph number. | ||
| 166 | ; | ||
| 167 | mov bx,ss ; bx = selector for stack | ||
| 168 | call SelToSeg ; AX = segment number for SS | ||
| 169 | mov bx,ax ; BX = setup stack segment | ||
| 170 | ; | ||
| 171 | ; | ||
| 172 | ; Intel shows DS,ES,FS,GS,and SS set up to make sure 'Real Mode' type | ||
| 173 | ; access rights, and limit are installed. In this program, that happens | ||
| 174 | ; to already be the case, but for general purposeness, VDMD_GSEL fits | ||
| 175 | ; the bill. | ||
| 176 | ; | ||
| 177 | mov ax,VDMD_GSEL ; selector with real mode attributes | ||
| 178 | mov ds,ax | ||
| 179 | mov es,ax | ||
| 180 | mov ss,ax | ||
| 181 | MOV_FS_AX | ||
| 182 | MOV_GS_AX | ||
| 183 | ; | ||
| 184 | ; Intel recommends the following code for resetting the PE bit. Mine | ||
| 185 | ; works OK, but maybe it's not general purpose enough (I was counting | ||
| 186 | ; on knowing that paging wasn't enabled). | ||
| 187 | ; | ||
| 188 | MOV_EAX_CR0 ; get CR0 | ||
| 189 | |||
| 190 | OP32 | ||
| 191 | and ax,0FFFEh ; force real mode and shut down paging | ||
| 192 | dw 07FFFh ; (mov eax,07FFFFFFEh) | ||
| 193 | |||
| 194 | MOV_CR0_EAX ; set CR0 | ||
| 195 | |||
| 196 | ; flush prefetched instructions with: | ||
| 197 | db 0EAh ; Far Jump opcode | ||
| 198 | dw offset _TEXT:rl386_b ; destination offset | ||
| 199 | Real_Seg label word | ||
| 200 | dw _TEXT ; destination segment | ||
| 201 | rl386_b: | ||
| 202 | OP32 ; load up full IDT address | ||
| 203 | lidt qword ptr cs:[real_idt] | ||
| 204 | |||
| 205 | sti | ||
| 206 | |||
| 207 | MOV_EAX_CR3 ; get CR3 | ||
| 208 | MOV_CR3_EAX ; set CR3 => clear TLB | ||
| 209 | |||
| 210 | mov ss,bx ; ss = real mode stack segment | ||
| 211 | mov ax,DGROUP | ||
| 212 | mov ds,ax | ||
| 213 | mov es,ax | ||
| 214 | MOV_FS_AX | ||
| 215 | MOV_GS_AX | ||
| 216 | |||
| 217 | mov [Active_Status],0 ; rest VDM status | ||
| 218 | |||
| 219 | call DisableA20 ; disable A20 line | ||
| 220 | |||
| 221 | pop bx | ||
| 222 | POP_EAX | ||
| 223 | ret ; *** RETURN *** | ||
| 224 | RetReal endp | ||
| 225 | |||
| 226 | _TEXT ends | ||
| 227 | end | ||
| 228 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU b/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU new file mode 100644 index 0000000..774afb1 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ROMSTRUC.EQU | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ROMSTRUC.EQU - structure of the option ROM headers. | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | OPTION_ROM STRUC | ||
| 32 | ROM_RECOGNITION DW ? ; HOLDS 0AA55 WORD IF REAL OPTION ROM | ||
| 33 | ROM_LEN DB ? ; BYTE HOLDING ROM SIZE / 512 | ||
| 34 | ROM_ENTRY DB ? ; WHERE CODE STARTS IN OPTION ROM | ||
| 35 | OPTION_ROM ENDS | ||
| 36 | |||
| 37 | .list ; end of ROMSTRUC.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU b/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU new file mode 100644 index 0000000..2ee4418 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ROMXBIOS.EQU | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: ROMXBIOS.EQU - ROM Extra BIOS function calls | ||
| 10 | ; | ||
| 11 | ; Version: 0.02 | ||
| 12 | ; | ||
| 13 | ; Date: June 25,1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; 06/25/86 Original | ||
| 24 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 25 | ; | ||
| 26 | ;****************************************************************************** | ||
| 27 | ifndef INC_LIST | ||
| 28 | .xlist | ||
| 29 | endif | ||
| 30 | |||
| 31 | XBIOS equ 15h ; Extra BIOS functions | ||
| 32 | DEV_OPEN equ 80h ; - device open dummy call | ||
| 33 | DEV_CLOSE equ 81h ; - device close dummy call | ||
| 34 | PROG_TERM equ 82h ; - program terminate | ||
| 35 | EVENT_WAIT equ 83h ; - Event Wait | ||
| 36 | JOYSTICK equ 84h ; - joystick | ||
| 37 | SYS_REQ equ 85h ; - sys request key routine | ||
| 38 | UNCOND_WAIT equ 86h ; - unconditional Wait | ||
| 39 | MOVE_BLK equ 87h ; - move block | ||
| 40 | EXT_MEM equ 88h ; - extended memory size | ||
| 41 | ENTER_PROT equ 89h ; - enter protected mode | ||
| 42 | DEV_WAIT equ 90h ; - Device Wait | ||
| 43 | DEV_POST equ 91h ; - Device Post | ||
| 44 | |||
| 45 | .list ; end of ROMXBIOS.EQU | ||
diff --git a/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM b/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM new file mode 100644 index 0000000..77da48a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/ROM_SRCH.ASM | |||
| @@ -0,0 +1,317 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ; | ||
| 4 | page 58,132 | ||
| 5 | ;****************************************************************************** | ||
| 6 | title ROM_SRCH - search for option ROMs | ||
| 7 | ;****************************************************************************** | ||
| 8 | ; | ||
| 9 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 10 | ; | ||
| 11 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 12 | ; | ||
| 13 | ; Module: ROM_SRCH - search for option ROMS and RAM | ||
| 14 | ; | ||
| 15 | ; Version: 0.04 | ||
| 16 | ; | ||
| 17 | ; Date : June 5,1986 | ||
| 18 | ; | ||
| 19 | ; Authors: SP, BT | ||
| 20 | ; | ||
| 21 | ;****************************************************************************** | ||
| 22 | ; | ||
| 23 | ; CHANGES: | ||
| 24 | ; | ||
| 25 | ; DATE REVISION DESCRIPTION | ||
| 26 | ; -------- -------- ------------------------------------------------------ | ||
| 27 | ; 06/05/86 Original Adapted from ROM code | ||
| 28 | ; 06/25/86 0.02 Fixed upd_map. | ||
| 29 | ; 06/26/86 0.02 Fixed upd_map (again) and ram_srch | ||
| 30 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 31 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 32 | ; 08/01/88 Updated to identify mappable segs between C000 and E000 | ||
| 33 | ; | ||
| 34 | ;****************************************************************************** | ||
| 35 | page | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional description: | ||
| 39 | ; | ||
| 40 | ; This module contains the code that scans the ROM at the segment | ||
| 41 | ; supplied in register AX looking for ROMs on hardware interface | ||
| 42 | ; boards. The layout of each valid ROM is as follows: | ||
| 43 | ; | ||
| 44 | ; OFFSET +-----------------------+ | ||
| 45 | ; 0 | 55h | | ||
| 46 | ; +-----------------------+ | ||
| 47 | ; 1 | AAh | | ||
| 48 | ; +-----------------------+ | ||
| 49 | ; 2 | ROM size / 512 | | ||
| 50 | ; +-----------------------+ | ||
| 51 | ; 3 | Start of init code | | ||
| 52 | ; : | ||
| 53 | ; n-1 | | | ||
| 54 | ; +-----------------------+ | ||
| 55 | ; (Sum of all bytes MOD 100h is 00h.) | ||
| 56 | ; | ||
| 57 | ; This module also contains the code to search and vector to VDU | ||
| 58 | ; roms (C000:0 to C000:7800 in 2K increments). | ||
| 59 | ; | ||
| 60 | ;****************************************************************************** | ||
| 61 | page | ||
| 62 | .386P | ||
| 63 | ; | ||
| 64 | ;****************************************************************************** | ||
| 65 | ; Public Declarations | ||
| 66 | ;****************************************************************************** | ||
| 67 | ; | ||
| 68 | public rom_srch ; Search and Vector to option ROMs. | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; Externs | ||
| 71 | ;****************************************************************************** | ||
| 72 | LAST segment | ||
| 73 | extrn Map_tbl:word | ||
| 74 | extrn max_PF:abs | ||
| 75 | extrn mappable_segs:byte | ||
| 76 | extrn exclude_segments:near | ||
| 77 | |||
| 78 | LAST ends | ||
| 79 | ; | ||
| 80 | ;****************************************************************************** | ||
| 81 | ; Equates | ||
| 82 | ;****************************************************************************** | ||
| 83 | ; | ||
| 84 | FIRST_ROM = 0C800H ; Segment address of first option ROM. | ||
| 85 | LAST_ROM = 0EF80H ; Segment address of last option ROM. | ||
| 86 | FIRST_VDU_ROM = 0C000H ; Seg address of first VDU option ROM. | ||
| 87 | LAST_VDU_ROM = 0C780H ; Seg address of last VDU option ROM. | ||
| 88 | FIRST_RAM = 0C000H ; Seg address of 1st possible RAM addr | ||
| 89 | LAST_RAM = 0EF80H ; Seg addr of last possible RAM addr | ||
| 90 | NOT_FOUND_INCR = 0800H ; Amount to skip if no ROM found. | ||
| 91 | ; | ||
| 92 | include emmdef.inc | ||
| 93 | include vdmseg.inc | ||
| 94 | include romstruc.equ ; Option ROM structure. | ||
| 95 | PF_LENGTH equ 0400h ; length of a page frame (*16) | ||
| 96 | ; | ||
| 97 | ;****************************************************************************** | ||
| 98 | ; S E G M E N T S | ||
| 99 | ;****************************************************************************** | ||
| 100 | LAST segment | ||
| 101 | ASSUME CS:LAST, DS:DGROUP | ||
| 102 | ; | ||
| 103 | page | ||
| 104 | ;****************************************************************************** | ||
| 105 | ; | ||
| 106 | ; ROM_SRCH - Search for option ROMs. | ||
| 107 | ; | ||
| 108 | ; This section of code searches the auxiliary rom area (from C8000 up | ||
| 109 | ; to E0000) in 2K increments. A ROM checksum is calculated to insure | ||
| 110 | ; that the ROMs are valid. Valid ROMs must have the 1st byte = 55H | ||
| 111 | ; and the next byte = 0AAH. The next byte indicates the size of the | ||
| 112 | ; ROM in 512-byte blocks. The sum of all bytes in the ROM, modulo 256, | ||
| 113 | ; must be zero. | ||
| 114 | ; | ||
| 115 | ; If a ROM is not found at a location, the next location 2K-bytes down | ||
| 116 | ; is examined. However, if it is found, the next location after this | ||
| 117 | ; ROM is tried. The next ROM location is determine according to the | ||
| 118 | ; size of the previous ROM. | ||
| 119 | ; | ||
| 120 | ; | ||
| 121 | ;****************************************************************************** | ||
| 122 | rom_srch proc near ; Entry point. | ||
| 123 | push bx | ||
| 124 | ; | ||
| 125 | ; search for option ROMs | ||
| 126 | ; | ||
| 127 | mov ax,FIRST_ROM ; Segment address of first option ROM. | ||
| 128 | cld ; Set direction flag. | ||
| 129 | nxt_opt: | ||
| 130 | call opt_rom ; Look for option ROM. | ||
| 131 | jnc not_fnd1 ; No ROM here | ||
| 132 | call upd_seg | ||
| 133 | not_fnd1: | ||
| 134 | cmp ax,LAST_ROM ;Q: All ROMs looked at ? | ||
| 135 | jbe nxt_opt ; No, keep looking | ||
| 136 | ; Y: check for VDU roms | ||
| 137 | ; | ||
| 138 | ; search for VDM ROMs | ||
| 139 | ; | ||
| 140 | mov ax,FIRST_VDU_ROM ; segment addr for first vdu ROM | ||
| 141 | cld | ||
| 142 | nxt_vdu: | ||
| 143 | call opt_rom ; Q:is it there | ||
| 144 | jnc not_fnd2 ; No ROM here | ||
| 145 | call upd_seg | ||
| 146 | not_fnd2: | ||
| 147 | cmp ax,LAST_VDU_ROM ;Q: last VDU ROM ? | ||
| 148 | jbe nxt_vdu ; N: continue | ||
| 149 | ; Y: check for RAM | ||
| 150 | ; | ||
| 151 | ; search for RAM | ||
| 152 | ; | ||
| 153 | mov ax,FIRST_RAM ; first seg addr for RAM search | ||
| 154 | cld | ||
| 155 | nxt_ram: | ||
| 156 | call ram_srch ;Q: RAM here ? | ||
| 157 | jnc not_fndr ; N: check again ? | ||
| 158 | call upd_seg | ||
| 159 | not_fndr: | ||
| 160 | cmp ax,LAST_RAM ;Q: last RAM location | ||
| 161 | jbe nxt_ram ; N: continue searching | ||
| 162 | ; Y: all done | ||
| 163 | ; | ||
| 164 | pop bx | ||
| 165 | ret | ||
| 166 | rom_srch endp | ||
| 167 | page | ||
| 168 | ; | ||
| 169 | ;****************************************************************************** | ||
| 170 | ; OPT_ROM - This routine looks at the ROM located at the segment address | ||
| 171 | ; specified in AX to see if 0TH and 1ST Bytes = 0AA55H. | ||
| 172 | ; If so, it calculates the checksum over the length of | ||
| 173 | ; ROM. If the checksum is valid it updates AX to point | ||
| 174 | ; to the location of the next ROM. | ||
| 175 | ; | ||
| 176 | ; Inputs: AX = Segment address of ROM. | ||
| 177 | ; | ||
| 178 | ; Outputs: CY = Found a VDU ROM at this location. | ||
| 179 | ; NC = Did not find a valid ROM at this location. | ||
| 180 | ; AX = Segment address of next ROM location. | ||
| 181 | ; DX = Length of this ROM | ||
| 182 | ; | ||
| 183 | ;****************************************************************************** | ||
| 184 | ; | ||
| 185 | opt_rom proc near | ||
| 186 | push bx | ||
| 187 | push cx | ||
| 188 | push si | ||
| 189 | push ds | ||
| 190 | ; | ||
| 191 | mov ds,ax ; DS=ROM segment address. | ||
| 192 | xor bx,bx ; Index uses less code than absolute. | ||
| 193 | cmp [bx.ROM_RECOGNITION],0AA55H ;Q: Looks like a ROM? | ||
| 194 | jne rs_3 ; No, Skip down | ||
| 195 | ; | ||
| 196 | ; Compute checksum over ROM. | ||
| 197 | ; | ||
| 198 | xor si,si ; DS:SI=ROM Pointer; Start at beg. | ||
| 199 | xor cx,cx ; Prepare to accept byte into word. | ||
| 200 | mov ch,[bx.ROM_LEN] ; CH=byte count/512 (CX=byte count/2) | ||
| 201 | shl cx,1 ; CX=adjusted byte count. | ||
| 202 | mov dx,cx ; Extract size. | ||
| 203 | rs_2: | ||
| 204 | lodsb ; MOV AL,DS:[SI+]; Pickup next byte. | ||
| 205 | add bl,al ; Checksum += byte(SEG:offset) | ||
| 206 | loop rs_2 ; Loop doesn't affect flags. | ||
| 207 | jnz rs_3 ; Jump down if bad checksum. | ||
| 208 | ; | ||
| 209 | mov cl,4 ; Shift of 4... | ||
| 210 | shr dx,cl ; Converts bytes to paragraphs (D.03) | ||
| 211 | mov ax,ds ; Replace segment in AX. | ||
| 212 | add ax,dx ; increment segment by this amount | ||
| 213 | stc ; rom found | ||
| 214 | jmp short rs_exit ; Continue. | ||
| 215 | ; | ||
| 216 | rs_3: | ||
| 217 | mov dx,(NOT_FOUND_INCR shr 4) ; Prepare for next ROM. | ||
| 218 | mov ax,ds ; Replace segment in AX. | ||
| 219 | add ax,dx ; Increment segment. | ||
| 220 | clc ; no rom found | ||
| 221 | ; | ||
| 222 | rs_exit: | ||
| 223 | pop ds | ||
| 224 | pop si | ||
| 225 | pop cx | ||
| 226 | pop bx | ||
| 227 | ret ; *** RETURN *** | ||
| 228 | ; | ||
| 229 | opt_rom endp | ||
| 230 | page | ||
| 231 | ; | ||
| 232 | ;****************************************************************************** | ||
| 233 | ; RAM_SRCH - This routine looks at the address range potentially used | ||
| 234 | ; by the Page Frame to determine if any RAM is in the way. | ||
| 235 | ; It updates the map accordingly. | ||
| 236 | ; | ||
| 237 | ; Inputs: AX = Segment address for RAM search. | ||
| 238 | ; | ||
| 239 | ; Outputs: CY = Found RAM at this location. | ||
| 240 | ; NC = Did not find RAM at this location. | ||
| 241 | ; AX = Segment address of next RAM location. | ||
| 242 | ; DX = Length of this RAM | ||
| 243 | ; | ||
| 244 | ;****************************************************************************** | ||
| 245 | ; | ||
| 246 | ram_srch proc near | ||
| 247 | |||
| 248 | push bx | ||
| 249 | push ds | ||
| 250 | ; | ||
| 251 | ; search for RAM | ||
| 252 | ; | ||
| 253 | xor dx,dx ; length = 0 | ||
| 254 | ram_loop: | ||
| 255 | mov ds,ax | ||
| 256 | add ax,(NOT_FOUND_INCR shr 4); prepare for next chunk | ||
| 257 | mov bx,ds:0 ; get a word | ||
| 258 | xor ds:0,0FFFFh ; flip all bits | ||
| 259 | xor bx,0FFFFh ; BX = "flipped" value | ||
| 260 | cmp bx,ds:0 ;Q: "flipped" value written out ? | ||
| 261 | jne no_more_ram ; N: not RAM - leave | ||
| 262 | xor ds:0,0FFFFh ; Y: is ram, flip bits back | ||
| 263 | add dx,(NOT_FOUND_INCR shr 4); increment length count | ||
| 264 | cmp ax,LAST_RAM ;Q: last RAM location ? | ||
| 265 | jbe ram_loop ; N: continue searching | ||
| 266 | mov ds,ax ; Y: no more searching | ||
| 267 | no_more_ram: | ||
| 268 | ; | ||
| 269 | mov ax,ds ; get current segment | ||
| 270 | or dx,dx ;Q: any RAM found ? | ||
| 271 | jnz ram_found ; Y: set RAM found & chk DS seg again | ||
| 272 | clc ; N: set no RAM | ||
| 273 | add ax,(NOT_FOUND_INCR shr 4) ; AX -> next one to check | ||
| 274 | jmp short ram_exit ; and leave | ||
| 275 | ; | ||
| 276 | ram_found: | ||
| 277 | stc | ||
| 278 | ram_exit: | ||
| 279 | pop ds | ||
| 280 | pop bx | ||
| 281 | ; | ||
| 282 | ret | ||
| 283 | ram_srch endp | ||
| 284 | page | ||
| 285 | ; | ||
| 286 | |||
| 287 | ;****************************************************************************** | ||
| 288 | ; UPD_SEG - This routine looks at the address range used by the ROM/RAM | ||
| 289 | ; that was found to determine how many potential physical | ||
| 290 | ; pages are invalidated from being mappable. It updates | ||
| 291 | ; the mappable_segs array appropriately. | ||
| 292 | ; | ||
| 293 | ; Inputs: AX = Segment address of next ROM/RAM position. | ||
| 294 | ; DX = Length of ROM/RAM | ||
| 295 | ; | ||
| 296 | ; Outputs: [mappable_segs] updated. | ||
| 297 | ; | ||
| 298 | ; Written: 8/1/88 ISP | ||
| 299 | ; Modif: 8/25/88 ISP to make use of exclude_segments | ||
| 300 | ;****************************************************************************** | ||
| 301 | upd_seg proc near | ||
| 302 | ; | ||
| 303 | push bx | ||
| 304 | push ax | ||
| 305 | ; | ||
| 306 | mov bx,ax | ||
| 307 | sub bx,dx ; bx now has the first segment of the area | ||
| 308 | dec ax ; and ax has the last segment of the area | ||
| 309 | ; | ||
| 310 | call exclude_segments | ||
| 311 | ; | ||
| 312 | pop ax | ||
| 313 | pop bx | ||
| 314 | ret | ||
| 315 | upd_seg endp | ||
| 316 | LAST ENDS | ||
| 317 | END | ||
diff --git a/v4.0/src/MEMM/MEMM/RRTRAP.ASM b/v4.0/src/MEMM/MEMM/RRTRAP.ASM new file mode 100644 index 0000000..c1bb1a7 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/RRTRAP.ASM | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title RRTRAP.ASM - Return To Real Trap | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: RRTRAP.ASM - Return to Real Trap | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/01/86 Original | ||
| 27 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 28 | ; 07/03/86 0.03 Changed to P84/85 Handlers | ||
| 29 | ; 07/06/86 0.04 Moved JumpReal to R_CODE and far label | ||
| 30 | ; 07/06/86 0.04 Changed assume to DGROUP | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ; | ||
| 34 | ; Functional Description: | ||
| 35 | ; This module traps ports 85h and 84h and watches for an application | ||
| 36 | ; to output the Return-to-Real code to these ports. If a 84h=0Fh is output, | ||
| 37 | ; then 85h=0h is output, the code in this module returns the system | ||
| 38 | ; to real mode. | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .lfcond ; list false conditionals | ||
| 43 | .386p | ||
| 44 | page | ||
| 45 | |||
| 46 | ;****************************************************************************** | ||
| 47 | ; I N C L U D E F I L E S | ||
| 48 | ; | ||
| 49 | include VDMseg.inc | ||
| 50 | include VDMsel.inc | ||
| 51 | include desc.inc | ||
| 52 | include INSTR386.INC | ||
| 53 | include VM386.INC | ||
| 54 | ; | ||
| 55 | ;****************************************************************************** | ||
| 56 | ; P U B L I C D E C L A R A T I O N S | ||
| 57 | ; | ||
| 58 | public RRP_Handler | ||
| 59 | public RR_Trap_Init | ||
| 60 | public RRProc | ||
| 61 | public JumpReal | ||
| 62 | ; | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; E X T E R N A L R E F E R E N C E S | ||
| 65 | ; | ||
| 66 | _TEXT segment | ||
| 67 | extrn RetReal:near | ||
| 68 | extrn PortTrap:near | ||
| 69 | _TEXT ends | ||
| 70 | |||
| 71 | page | ||
| 72 | ;****************************************************************************** | ||
| 73 | ; L O C A L C O N S T A N T S | ||
| 74 | ; | ||
| 75 | FALSE equ 0 | ||
| 76 | TRUE equ not FALSE | ||
| 77 | |||
| 78 | RR85_Value equ 00h | ||
| 79 | RR84_Value equ 0Fh | ||
| 80 | |||
| 81 | FLAGS_IF equ 0200h | ||
| 82 | FLAGS_TF equ 0100h | ||
| 83 | |||
| 84 | RR_MASK equ NOT (FLAGS_IF+FLAGS_TF) ; mask off IF and TF bits | ||
| 85 | |||
| 86 | RTC_CMD equ 70h ; real time clock command port | ||
| 87 | DISABLE_NMI equ 80h ; cmd to disable NMI | ||
| 88 | ENABLE_NMI equ 00h ; cmd to enable NMI | ||
| 89 | |||
| 90 | ; | ||
| 91 | ;****************************************************************************** | ||
| 92 | ; D A T A S E G M E N T D E F I N I T I O N S | ||
| 93 | ; | ||
| 94 | ABS0 segment at 0000h | ||
| 95 | ABS0 ends | ||
| 96 | ; | ||
| 97 | _DATA segment | ||
| 98 | RR_Last db 0 ; last RR port trapped | ||
| 99 | RR85save db 0FFh | ||
| 100 | RR84save db 0FFh | ||
| 101 | _DATA ends | ||
| 102 | |||
| 103 | ; | ||
| 104 | ;------------------------------------------------------------------------------ | ||
| 105 | ; _TEXT code | ||
| 106 | ;------------------------------------------------------------------------------ | ||
| 107 | _TEXT segment | ||
| 108 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 109 | |||
| 110 | page | ||
| 111 | ;****************************************************************************** | ||
| 112 | ; RRP_Handler - I/O Trap handler for return to real ports 84h and 85h | ||
| 113 | ; | ||
| 114 | ; ENTRY: Protected Mode Ring 0 | ||
| 115 | ; AL = byte to output to port. | ||
| 116 | ; BX = 2 * port addr | ||
| 117 | ; DX == 0 => input | ||
| 118 | ; <> 0 => output | ||
| 119 | ; DS = DGROUP | ||
| 120 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 121 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 122 | ; then GP fault stack frame with error code. | ||
| 123 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 124 | ; | ||
| 125 | ; EXIT: Protected Mode Ring 0 | ||
| 126 | ; CLC => I/O emulated. | ||
| 127 | ; STC => I/O NOT emulated. | ||
| 128 | ; | ||
| 129 | ; USED: Flags | ||
| 130 | ; STACK: | ||
| 131 | ;------------------------------------------------------------------------------ | ||
| 132 | RRP_Handler proc near | ||
| 133 | or dx,dx ;Q: Output ? | ||
| 134 | jz RRP_Bye ; N: then leave | ||
| 135 | cmp bx,84h*2 | ||
| 136 | je P84_Handler ; Process port 84h | ||
| 137 | cmp bx,85h*2 | ||
| 138 | je P85_Handler ; Process port 85h | ||
| 139 | RRP_Bye: | ||
| 140 | stc ; don't bother to emulate it | ||
| 141 | ret | ||
| 142 | RRP_Handler endp | ||
| 143 | |||
| 144 | ;****************************************************************************** | ||
| 145 | ; P84_Handler - I/O Trap handler for port 84h | ||
| 146 | ; | ||
| 147 | ; ENTRY: Protected Mode Ring 0 | ||
| 148 | ; AL = byte to output to port. | ||
| 149 | ; BX = 2 * port addr | ||
| 150 | ; DX == 0 => input | ||
| 151 | ; <> 0 => output | ||
| 152 | ; DS = DGROUP | ||
| 153 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 154 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 155 | ; then GP fault stack frame with error code. | ||
| 156 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 157 | ; | ||
| 158 | ; EXIT: Protected Mode Ring 0 | ||
| 159 | ; CLC => I/O emulated. | ||
| 160 | ; STC => I/O NOT emulated. | ||
| 161 | ; | ||
| 162 | ; USED: Flags | ||
| 163 | ; STACK: | ||
| 164 | ;------------------------------------------------------------------------------ | ||
| 165 | P84_Handler proc near | ||
| 166 | ; | ||
| 167 | mov [RR84save],al ; Y: save value written to 84 | ||
| 168 | mov [RR_Last],84h ; save this RR port # | ||
| 169 | stc ; don't bother to emulate it | ||
| 170 | ret | ||
| 171 | ; | ||
| 172 | P84_Handler endp | ||
| 173 | |||
| 174 | page | ||
| 175 | ;****************************************************************************** | ||
| 176 | ; P85_Handler - I/O Trap handler for port 85h | ||
| 177 | ; | ||
| 178 | ; ENTRY: Protected Mode Ring 0 | ||
| 179 | ; AL = byte to output to port. | ||
| 180 | ; BX = 2 * port addr | ||
| 181 | ; DX == 0 => input | ||
| 182 | ; <> 0 => output | ||
| 183 | ; DS = DGROUP | ||
| 184 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 185 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 186 | ; then GP fault stack frame with error code. | ||
| 187 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 188 | ; | ||
| 189 | ; EXIT: If output to 85h => return to Real | ||
| 190 | ; RRTrap emulates the output to 85h | ||
| 191 | ; RRTrap returns to real, fixes the segments and stack, and | ||
| 192 | ; returns to the instruction past the output in real mode. | ||
| 193 | ; If output does not imply return to Real | ||
| 194 | ; Protected Mode Ring 0 | ||
| 195 | ; CLC => I/O emulated. | ||
| 196 | ; STC => I/O NOT emulated. | ||
| 197 | ; | ||
| 198 | ; USED: Flags | ||
| 199 | ; STACK: | ||
| 200 | ;------------------------------------------------------------------------------ | ||
| 201 | P85_Handler proc near | ||
| 202 | ; | ||
| 203 | mov [RR85save],al ; Y: save value for 85h | ||
| 204 | cmp al,RR85_Value ; Q: return to real value output to 85 ? | ||
| 205 | jne P85_Exit ; N: save port # and leave | ||
| 206 | cmp [RR_Last],84h ; Y: Q: was last 84h last RR port output ? | ||
| 207 | jne P85_Exit ; N: save port # and leave | ||
| 208 | cmp [RR84Save],RR84_Value ; Y: Q: was 84h value RR value ? | ||
| 209 | jne P85_Exit ; N: save port # and leave | ||
| 210 | out 85h,al ; Y: emulate output and | ||
| 211 | jmp RR_GoReal ; return to real(we're in real) | ||
| 212 | P85_Exit: | ||
| 213 | mov [RR_Last],85h ; save this RR port addr | ||
| 214 | stc ; don't bother to emulate it | ||
| 215 | ret | ||
| 216 | ; | ||
| 217 | P85_Handler endp | ||
| 218 | |||
| 219 | page | ||
| 220 | ;****************************************************************************** | ||
| 221 | ; RR_GoReal - return client to real after 84/85 trap | ||
| 222 | ; | ||
| 223 | ; This is the return to real code. First we return to real mode. | ||
| 224 | ; Then we set up the stack, restore the registers and return to | ||
| 225 | ; the instruction following the out to 85h. | ||
| 226 | ;************** | ||
| 227 | ;NOTE: the following depends on the entry stack for P85_Handler | ||
| 228 | ; the same. | ||
| 229 | ; ENTRY: | ||
| 230 | ; SS:SP pts to: IP, saved DS, saved DX, IP , | ||
| 231 | ; saved DX,saved BX,saved ESI,saved EBX,saved EBP, | ||
| 232 | ; then GP fault stack frame with error code. | ||
| 233 | ;************** | ||
| 234 | ;****************************************************************************** | ||
| 235 | ; | ||
| 236 | RR_GoReal: | ||
| 237 | push ax | ||
| 238 | mov al,DISABLE_NMI | ||
| 239 | out RTC_CMD,al ; disable NMIs | ||
| 240 | pop ax | ||
| 241 | |||
| 242 | call RetReal ; return to real mode, DS,ES = DGROUP | ||
| 243 | ; | ||
| 244 | ; now start resetting registers from the stack | ||
| 245 | ; | ||
| 246 | ; | ||
| 247 | add sp,8 ; skip IP,DS,DX, and IP | ||
| 248 | pop dx | ||
| 249 | pop bx ; last pushed by OUT emulator | ||
| 250 | ; | ||
| 251 | ; now back to stack presented by VmFault's jmp to instr handler | ||
| 252 | ; | ||
| 253 | ; on to JumpReal code and continue in Real mode | ||
| 254 | ; | ||
| 255 | jmp FAR PTR JumpReal | ||
| 256 | |||
| 257 | ;****************************************************************************** | ||
| 258 | ; | ||
| 259 | ; RRProc Force processor into real mode | ||
| 260 | ; | ||
| 261 | ; entry: | ||
| 262 | ; | ||
| 263 | ; exit: Processor is in real mode | ||
| 264 | ; | ||
| 265 | ; used: AX | ||
| 266 | ; | ||
| 267 | ; stack: | ||
| 268 | ; | ||
| 269 | ;****************************************************************************** | ||
| 270 | RRProc proc near | ||
| 271 | pushf | ||
| 272 | cli ; protect this sequence | ||
| 273 | mov al,RR84_Value ; | ||
| 274 | out 84h,al ; port 84/85 return to real | ||
| 275 | mov al,RR85_Value ; sequence ... | ||
| 276 | out 85h,al ; | ||
| 277 | jmp $+2 ; clear prefetch/avoid race cond | ||
| 278 | popf | ||
| 279 | ret | ||
| 280 | RRProc endp | ||
| 281 | |||
| 282 | ;****************************************************************************** | ||
| 283 | ; | ||
| 284 | ; RR_Trap_Init Initialize data structure for return to real trapping | ||
| 285 | ; | ||
| 286 | ; description: This routine is called when the processor is put in | ||
| 287 | ; virtual mode. It should initialize anything that is | ||
| 288 | ; used by the RRTrap code. It assumes that the handler | ||
| 289 | ; addresses for ports 84h and 85h in IOTrap_Tab are set | ||
| 290 | ; up to point to RRP_Handler. | ||
| 291 | ; | ||
| 292 | ; entry: DS pts to DGROUP | ||
| 293 | ; | ||
| 294 | ; exit: Return to real trapping data structure initialized | ||
| 295 | ; | ||
| 296 | ; used: AX, BX | ||
| 297 | ; | ||
| 298 | ; stack: | ||
| 299 | ; | ||
| 300 | ;****************************************************************************** | ||
| 301 | RR_Trap_Init proc near | ||
| 302 | mov [RR_Last],0 ; reset Return to real trap vars | ||
| 303 | mov [RR85save],0FFh | ||
| 304 | mov [RR84save],0FFh | ||
| 305 | mov bh, 00h ; only set for 0084h and 0085h | ||
| 306 | mov ax, 84h | ||
| 307 | call PortTrap ; set traps on both return to real | ||
| 308 | mov ax, 85h ; ports in case client tries to | ||
| 309 | call PortTrap ; return to real | ||
| 310 | ret | ||
| 311 | RR_Trap_Init endp | ||
| 312 | |||
| 313 | _TEXT ends ; end of segment | ||
| 314 | |||
| 315 | ;------------------------------------------------------------------------------ | ||
| 316 | ; R_CODE code | ||
| 317 | ;------------------------------------------------------------------------------ | ||
| 318 | R_CODE segment | ||
| 319 | assume cs:R_CODE, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 320 | ; | ||
| 321 | ;****************************************************************************** | ||
| 322 | ; L O C A L D A T A A R E A | ||
| 323 | ;****************************************************************************** | ||
| 324 | ; | ||
| 325 | RR_Jump label dword ; ret addr for instr after out 84 | ||
| 326 | RR_JOff dw 0 | ||
| 327 | RR_JSeg dw 0 | ||
| 328 | |||
| 329 | RR_DS dw 0 ; DS for return | ||
| 330 | RR_SS dw 0 ; SS for return | ||
| 331 | RR_SP dw 0 ; SP for return | ||
| 332 | |||
| 333 | RR_Flags dw 0 ; low word of flags for return | ||
| 334 | |||
| 335 | ;****************************************************************************** | ||
| 336 | ; | ||
| 337 | ; NAME: JumpReal - jump into faulting code and continuing executing in Real | ||
| 338 | ; mode. When a virtual mode process causes a GP fault, then wishes | ||
| 339 | ; to continue executing in Real mode afterwards, VDM returns to real | ||
| 340 | ; mode then calls this routine to "unwind" the stack and continue | ||
| 341 | ; the process in real mode. | ||
| 342 | ; | ||
| 343 | ; THIS IS A FAR JUMP *** | ||
| 344 | ; | ||
| 345 | ; ENTRY: REAL MODE | ||
| 346 | ; SS:[BP] -> points to GP fault stack frame | ||
| 347 | ; SS:[SP] = saved client's ESI | ||
| 348 | ; SS:[SP+4] = saved client's EBX | ||
| 349 | ; SS:[SP+8] = saved client's EBP | ||
| 350 | ; | ||
| 351 | ; EXIT: REAL MODE | ||
| 352 | ; continues execution of process specified in GP fault stack | ||
| 353 | ; frame. | ||
| 354 | ; | ||
| 355 | ;****************************************************************************** | ||
| 356 | JumpReal label far | ||
| 357 | push cs | ||
| 358 | pop ds ; set DS= CS = R_CODE | ||
| 359 | ASSUME DS:R_CODE | ||
| 360 | ; set up return address | ||
| 361 | mov bx,[bp.VTFOE+VMTF_EIP] ; get return IP | ||
| 362 | mov [RR_JOff],bx ; save it | ||
| 363 | mov bx,[bp.VTFOE+VMTF_CS] ; get return CS | ||
| 364 | mov [RR_JSeg],bx ; save it | ||
| 365 | ; | ||
| 366 | mov bx,[bp.VTFOE+VMTF_EFLAGS] ; get flags | ||
| 367 | mov [RR_Flags],bx ; and save | ||
| 368 | and [bp.VTFOE+VMTF_EFLAGS],RR_MASK ; mask off certain bits | ||
| 369 | ; | ||
| 370 | mov bx,[bp.VTFOE+VMTF_DS] ; get DS | ||
| 371 | mov [RR_DS],bx ; save it | ||
| 372 | |||
| 373 | mov bx,[bp.VTFOE+VMTF_SS] ; get SS | ||
| 374 | mov [RR_SS],bx ; save it | ||
| 375 | mov bx,[bp.VTFOE+VMTF_ESP] ; get SP | ||
| 376 | mov [RR_SP],bx ; save it | ||
| 377 | ; | ||
| 378 | ; restore regs pushed by VM_Fault entry | ||
| 379 | ; | ||
| 380 | POP_ESI | ||
| 381 | POP_EBX | ||
| 382 | POP_EBP ; ALL regs except SEGMENT and SP are | ||
| 383 | ; restored. | ||
| 384 | add sp,4+VMTF_ES ; skip error code and GP fault stack | ||
| 385 | ; up to ES | ||
| 386 | |||
| 387 | pop es ; reset ES for return | ||
| 388 | add sp,6 ; skip high word of ES segment | ||
| 389 | ; and DS dword | ||
| 390 | |||
| 391 | POP_FS ; reset FS for return | ||
| 392 | add sp,2 ; skip high word of segment | ||
| 393 | |||
| 394 | POP_GS ; reset GS for return | ||
| 395 | ; | ||
| 396 | ; now set flags, DS, stack, and jump to return. | ||
| 397 | ; | ||
| 398 | test [RR_Flags],FLAGS_IF ;Q: IF bit set in return flags ? | ||
| 399 | jz RR_CLIexit ; N: then just return | ||
| 400 | push [RR_Flags] ; Y: enable interrupts on return | ||
| 401 | popf ; set flags | ||
| 402 | push [RR_DS] | ||
| 403 | pop ds ; set DS for exit | ||
| 404 | push ax | ||
| 405 | mov al,ENABLE_NMI | ||
| 406 | out RTC_CMD,al ; enable NMIs | ||
| 407 | pop ax | ||
| 408 | ;*** there is a small window here | ||
| 409 | ; --- NMI could occur with invalid | ||
| 410 | ; STACK | ||
| 411 | |||
| 412 | mov ss,CS:[RR_SS] ; restore SS | ||
| 413 | mov sp,CS:[RR_SP] ; restore SP | ||
| 414 | sti ; enable ints | ||
| 415 | jmp CS:[RR_Jump] ; and return | ||
| 416 | |||
| 417 | RR_CLIexit: | ||
| 418 | push [RR_Flags] ; leave interrupts disabled on return | ||
| 419 | popf ; set flags | ||
| 420 | push [RR_DS] | ||
| 421 | pop ds ; set DS for exit | ||
| 422 | push ax | ||
| 423 | mov al,ENABLE_NMI | ||
| 424 | out RTC_CMD,al ; enable NMIs | ||
| 425 | pop ax | ||
| 426 | ;*** there is a small window here | ||
| 427 | ; --- NMI could occur with invalid | ||
| 428 | ; STACK | ||
| 429 | |||
| 430 | mov ss,CS:[RR_SS] ; restore SS | ||
| 431 | mov sp,CS:[RR_SP] ; restore SP | ||
| 432 | jmp CS:[RR_Jump] ; far jump for return | ||
| 433 | ; | ||
| 434 | R_CODE ends ; end of segment | ||
| 435 | ; | ||
| 436 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/SHIPHI.ASM b/v4.0/src/MEMM/MEMM/SHIPHI.ASM new file mode 100644 index 0000000..be09a96 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/SHIPHI.ASM | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | TITLE SHIPHI - MODULE to ship a segment up hi | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: SHIPHI - Ship a segment up hi into extended memory | ||
| 13 | ; | ||
| 14 | ; Version: 0.01 | ||
| 15 | ; | ||
| 16 | ; Date: Sep 1, 1988 | ||
| 17 | ; | ||
| 18 | ; Author: ISP | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change Log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION Description | ||
| 25 | ; -------- -------- -------------------------------------------- | ||
| 26 | ;****************************************************************************** | ||
| 27 | ; Functional Description: | ||
| 28 | ; | ||
| 29 | ; We need to ship data structures up hi. | ||
| 30 | ; This file has routines to specify size requirements for this operation | ||
| 31 | ; and to shift a segment up hi. Remember that in shipping a segment up hi | ||
| 32 | ; the GDT segment should be the last to be sent up since it is modified while | ||
| 33 | ; shipping a segment up hi | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | .lfcond | ||
| 37 | .386p | ||
| 38 | |||
| 39 | page | ||
| 40 | ;****************************************************************************** | ||
| 41 | ; P U B L I C D E C L A R A T I O N S | ||
| 42 | ;****************************************************************************** | ||
| 43 | public set_src_selector ; Routines and data(GDT) for move block | ||
| 44 | public set_dest_selector | ||
| 45 | public moveb | ||
| 46 | public memreq | ||
| 47 | |||
| 48 | public gdt_mb | ||
| 49 | |||
| 50 | |||
| 51 | page | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; L O C A L C O N S T A N T S | ||
| 54 | ;****************************************************************************** | ||
| 55 | ; | ||
| 56 | |||
| 57 | ;****************************************************************************** | ||
| 58 | ; INCLUDE FILES | ||
| 59 | ;****************************************************************************** | ||
| 60 | include vdmseg.inc ; segment definitions | ||
| 61 | include desc.inc ; | ||
| 62 | include page.inc | ||
| 63 | |||
| 64 | page | ||
| 65 | ;****************************************************************************** | ||
| 66 | ; E X T E R N A L R E F E R E N C E S | ||
| 67 | ;****************************************************************************** | ||
| 68 | ; | ||
| 69 | ; | ||
| 70 | LAST SEGMENT | ||
| 71 | extrn get_buffer:near | ||
| 72 | LAST ENDS | ||
| 73 | |||
| 74 | page | ||
| 75 | ;****************************************************************************** | ||
| 76 | ; S E G M E N T D E F I N I T I O N | ||
| 77 | ;****************************************************************************** | ||
| 78 | |||
| 79 | ;************************************************************************* | ||
| 80 | ; | ||
| 81 | ; DATA | ||
| 82 | ; | ||
| 83 | ;************************************************************************* | ||
| 84 | |||
| 85 | _DATA SEGMENT | ||
| 86 | ASSUME CS:DGROUP,DS:DGROUP | ||
| 87 | ; | ||
| 88 | _DATA ENDS | ||
| 89 | |||
| 90 | |||
| 91 | |||
| 92 | |||
| 93 | LAST SEGMENT | ||
| 94 | ASSUME CS:LAST,DS:DGROUP,ES:DGROUP | ||
| 95 | |||
| 96 | ; GDT for ROM Move Block calls | ||
| 97 | ; | ||
| 98 | gdt_mb label word | ||
| 99 | ; | ||
| 100 | gdt0_mb: GDT_ENTRY 0,0,1,0 ; Dummy seg descriptor | ||
| 101 | gdt1_mb: GDT_ENTRY 0,0,1,0 ; GDT seg descriptor | ||
| 102 | gdt2_mb: GDT_ENTRY 0,0,0,D_DATA3 ; Src seg descriptor | ||
| 103 | gdt3_mb: GDT_ENTRY 0,0,0,D_DATA3 ; Dest seg descriptor | ||
| 104 | gdt4_mb: GDT_ENTRY 0,0,1,0 ; Bios cs seg descriptor | ||
| 105 | gdt5_mb: GDT_ENTRY 0,0,1,0 ; Bios ss seg descriptor | ||
| 106 | ; | ||
| 107 | |||
| 108 | LAST ENDS | ||
| 109 | |||
| 110 | ;************************************************************************* | ||
| 111 | ; | ||
| 112 | ; CODE | ||
| 113 | ; | ||
| 114 | ;************************************************************************* | ||
| 115 | LAST SEGMENT | ||
| 116 | ASSUME CS:LAST,DS:DGROUP,ES:DGROUP | ||
| 117 | |||
| 118 | ;****************************************************************************** | ||
| 119 | ; SHIPHI - routine to ship a segment up hi ; | ||
| 120 | ; ; | ||
| 121 | ; INPUTS: es = segment to be moved up ; | ||
| 122 | ; cx = number of bytes in the segment ; | ||
| 123 | ; ; | ||
| 124 | ; OUTPUTS: dx:ax = new address of the segment ; | ||
| 125 | ; Z set if succeeded, NZ if error ; | ||
| 126 | ; ; | ||
| 127 | ; USES: ax,dx,flags ; | ||
| 128 | ; ; | ||
| 129 | ; CALLS: ; | ||
| 130 | ; ; | ||
| 131 | ; AUTHOR: ISP (ISP) Sep 2, 1988 ; | ||
| 132 | ; ; | ||
| 133 | ;*****************************************************************************; | ||
| 134 | SHIPHI proc near | ||
| 135 | ; | ||
| 136 | push di | ||
| 137 | ; | ||
| 138 | ; first get some memory to play with | ||
| 139 | ; | ||
| 140 | call get_buffer | ||
| 141 | ; | ||
| 142 | ; then move the segment up to this new segment | ||
| 143 | ; | ||
| 144 | xor dh,dh ; dx:ax 32 bit addr of dest | ||
| 145 | xor di,di ; es:di is source segment | ||
| 146 | call moveb | ||
| 147 | ; | ||
| 148 | pop di | ||
| 149 | ; | ||
| 150 | ret | ||
| 151 | SHIPHI endp | ||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | ;*****************************************************************************; | ||
| 156 | ;*** MOVEB *** ; | ||
| 157 | ; ; | ||
| 158 | ; Move data between from conventional memory to extended memory ; | ||
| 159 | ; ; | ||
| 160 | ; ; | ||
| 161 | ; INPUTS: dl:ax = 24 bit address of extended memory address ; | ||
| 162 | ; es:di = source address in lo memory | ||
| 163 | ; cx = number of bytes to transfer | ||
| 164 | ; ; | ||
| 165 | ; OUTPUTS: Z set if succeeded ; | ||
| 166 | ; NZ if error ; | ||
| 167 | ; ; | ||
| 168 | ; USES: ; | ||
| 169 | ; ; | ||
| 170 | ; AUTHOR: ISP, Sep 2,1988. ; | ||
| 171 | ; ; | ||
| 172 | ;*****************************************************************************; | ||
| 173 | |||
| 174 | |||
| 175 | MOVEB proc near | ||
| 176 | push es | ||
| 177 | push dx | ||
| 178 | push ax | ||
| 179 | push di | ||
| 180 | push cx | ||
| 181 | |||
| 182 | |||
| 183 | ; | ||
| 184 | ; no setup needed for dest selector, already set up. | ||
| 185 | ; | ||
| 186 | call set_dest_selector ; destination is unlock address | ||
| 187 | ; | ||
| 188 | ; for source selector we need to convert segment:offset to dl:ax | ||
| 189 | ; cx is already # of words | ||
| 190 | ; | ||
| 191 | xor dx,dx | ||
| 192 | mov ax,es | ||
| 193 | mov bx,16 | ||
| 194 | mul bx | ||
| 195 | add ax,di | ||
| 196 | adc dx,0 | ||
| 197 | |||
| 198 | call set_src_selector ; set source segment selector to buffer | ||
| 199 | ; | ||
| 200 | ; do the block move | ||
| 201 | ; | ||
| 202 | mov si,seg LAST | ||
| 203 | mov es,si | ||
| 204 | mov si,offset LAST:gdt_mb ; ES:SI -> global descriptor table | ||
| 205 | ; | ||
| 206 | ; convert count to number of words | ||
| 207 | ; | ||
| 208 | inc cx | ||
| 209 | shr cx,1 | ||
| 210 | ; | ||
| 211 | ; | ||
| 212 | mov ah,87h ; int 15 block move function code | ||
| 213 | int 15h ; unlock rom | ||
| 214 | or ah,ah ; Q: error? | ||
| 215 | ; Y: return NZ | ||
| 216 | pop cx | ||
| 217 | pop di | ||
| 218 | pop ax | ||
| 219 | pop dx | ||
| 220 | pop es | ||
| 221 | ; N: return Z | ||
| 222 | ret | ||
| 223 | MOVEB endp | ||
| 224 | |||
| 225 | page | ||
| 226 | ;****************************************************************************** | ||
| 227 | ; | ||
| 228 | ; set_src_selector | ||
| 229 | ; Set base address, limit of source segment selector | ||
| 230 | ; in gdt_mb for int 15h block move | ||
| 231 | ; | ||
| 232 | ; | ||
| 233 | ; entry: dl:ax == source address (24 bits) | ||
| 234 | ; cx == size, in words | ||
| 235 | ; | ||
| 236 | ; exit: gdt_mb(2) contains source base address, limit | ||
| 237 | ; | ||
| 238 | ; used: none | ||
| 239 | ; | ||
| 240 | ;****************************************************************************** | ||
| 241 | ; | ||
| 242 | set_src_selector proc near | ||
| 243 | ; | ||
| 244 | push di | ||
| 245 | mov di,offset LAST:gdt2_mb ; cs:di -> source seg descriptor | ||
| 246 | set_entry: | ||
| 247 | mov cs:[di.BASE_LOW],ax ; Store base address bits 15:00 | ||
| 248 | mov cs:[di.BASE_HIGH],dl ; Store base address bits 23:16 | ||
| 249 | mov cs:[di.LIMIT],cx ; Store size | ||
| 250 | sub cs:[di.LIMIT],1 ; subtract 1 => convert to limit | ||
| 251 | ; | ||
| 252 | pop di | ||
| 253 | ret ; *** Return *** | ||
| 254 | ; | ||
| 255 | set_src_selector endp ; End of procedure | ||
| 256 | ; | ||
| 257 | page | ||
| 258 | ;****************************************************************************** | ||
| 259 | ; | ||
| 260 | ; set_dest_selector | ||
| 261 | ; Set base address, limit of destination segment selector | ||
| 262 | ; in gdt_mb for int 15h block move | ||
| 263 | ; | ||
| 264 | ; entry: dx:ax == address (32 bits) | ||
| 265 | ; cx == size of segment, in words | ||
| 266 | ; ds = DGROUP | ||
| 267 | ; | ||
| 268 | ; exit: gdt_mb(3) contains destination base address, | ||
| 269 | ; limit | ||
| 270 | ; | ||
| 271 | ; used: none | ||
| 272 | ; | ||
| 273 | ;****************************************************************************** | ||
| 274 | ; | ||
| 275 | set_dest_selector proc near | ||
| 276 | ; | ||
| 277 | push di | ||
| 278 | mov di,offset LAST:gdt3_mb ; cs:di -> source seg descriptor | ||
| 279 | mov cs:[di.BASE_XHI],dh ; bits 24-31 | ||
| 280 | jmp set_entry ; set this entry in gdt_mb | ||
| 281 | ; | ||
| 282 | ret ; *** Return *** | ||
| 283 | ; | ||
| 284 | set_dest_selector endp ; End of procedure | ||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | ;****************************************************************************** | ||
| 293 | ; MEMREQ - routine to determine memory requirements for shifting the driver ; | ||
| 294 | ; up into extended memory ; | ||
| 295 | ; ; | ||
| 296 | ; INPUTS: none ; | ||
| 297 | ; ; | ||
| 298 | ; OUTPUTS: CX = size requirements in K ; | ||
| 299 | ; ; | ||
| 300 | ; USES: CX, flags ; | ||
| 301 | ; ; | ||
| 302 | ; AUTHOR: ISP (ISP) Sep 2, 1988 ; | ||
| 303 | ; ; | ||
| 304 | ;*****************************************************************************; | ||
| 305 | MEMREQ proc near | ||
| 306 | ; | ||
| 307 | push ax | ||
| 308 | ; | ||
| 309 | mov ax,seg LAST ; this is the last segment and | ||
| 310 | ; one which is discarded. | ||
| 311 | sub ax,seg PAGESEG ; this is the first segment of the | ||
| 312 | ; region which is to be moved. | ||
| 313 | |||
| 314 | add ax, (P_SIZE/16 -1) ; to round it up to next page bdry | ||
| 315 | shr ax, 6 ; find the size in K | ||
| 316 | add ax,16 ; throw in 4 more pages for safety | ||
| 317 | mov cx,ax ; and return the size needed | ||
| 318 | ; | ||
| 319 | pop ax | ||
| 320 | ret | ||
| 321 | MEMREQ endp | ||
| 322 | |||
| 323 | LAST ENDS | ||
| 324 | |||
| 325 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/TABDEF.ASM b/v4.0/src/MEMM/MEMM/TABDEF.ASM new file mode 100644 index 0000000..c70406e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/TABDEF.ASM | |||
| @@ -0,0 +1,357 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title TABDEF.ASM - 386 Protected Mode CPU Tables | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: TABDEF.ASM - 386 Protected Mode CPU Tables | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 31, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/31/86 Tables for Standalone protected mode system | ||
| 27 | ; A- Modified for Virtual DOS | ||
| 28 | ; 05/12/86 B- Cleanup and segment reorganization | ||
| 29 | ; 06/28/86 0.02 Name changed from MEMM386 to MEMM | ||
| 30 | ; 07/05/86 0.04 Moved KBD and PRINT to DCODE segment | ||
| 31 | ; 07/20/88 Remove debugger codes (pc) | ||
| 32 | ; | ||
| 33 | ;****************************************************************************** | ||
| 34 | ; | ||
| 35 | ; Functional Description: | ||
| 36 | ; | ||
| 37 | ;****************************************************************************** | ||
| 38 | .lfcond ; list false conditionals | ||
| 39 | .386p | ||
| 40 | |||
| 41 | NAME tabdef | ||
| 42 | ; | ||
| 43 | |||
| 44 | .xlist | ||
| 45 | include VDMseg.inc | ||
| 46 | include VDMsel.inc | ||
| 47 | include desc.inc | ||
| 48 | include page.inc | ||
| 49 | .list | ||
| 50 | |||
| 51 | |||
| 52 | _TEXT SEGMENT | ||
| 53 | extrn vm_trap00:far | ||
| 54 | extrn vm_trap01:far | ||
| 55 | extrn vm_trap02:far | ||
| 56 | extrn vm_trap03:far | ||
| 57 | extrn vm_trap04:far | ||
| 58 | extrn vm_trap05:far | ||
| 59 | extrn vm_trap06:far | ||
| 60 | extrn vm_trap07:far | ||
| 61 | extrn vm_trap08:far | ||
| 62 | extrn vm_trap09:far | ||
| 63 | extrn vm_trap0a:far | ||
| 64 | extrn vm_trap0b:far | ||
| 65 | extrn vm_trap0c:far | ||
| 66 | extrn vm_trap0d:far | ||
| 67 | extrn vm_trap0e:far | ||
| 68 | extrn vm_trap0f:far | ||
| 69 | extrn vm_trap50:far | ||
| 70 | extrn vm_trap51:far | ||
| 71 | extrn vm_trap52:far | ||
| 72 | extrn vm_trap53:far | ||
| 73 | extrn vm_trap54:far | ||
| 74 | extrn vm_trap55:far | ||
| 75 | extrn vm_trap56:far | ||
| 76 | extrn vm_trap57:far | ||
| 77 | extrn vm_trap70:far | ||
| 78 | extrn vm_trap71:far | ||
| 79 | extrn vm_trap72:far | ||
| 80 | extrn vm_trap73:far | ||
| 81 | extrn vm_trap74:far | ||
| 82 | extrn vm_trap75:far | ||
| 83 | extrn vm_trap76:far | ||
| 84 | extrn vm_trap77:far | ||
| 85 | |||
| 86 | extrn EMM_pEntry:far | ||
| 87 | |||
| 88 | _TEXT ENDS | ||
| 89 | |||
| 90 | |||
| 91 | ;*** GDT - Global Descriptor Table | ||
| 92 | ; | ||
| 93 | ; This is the system GDT. Some parts are statically initialised, | ||
| 94 | ; others must be set up at run time, either because masm can't | ||
| 95 | ; calculate the data or it changes while the system is running. | ||
| 96 | ; | ||
| 97 | ; WARNING | ||
| 98 | ; | ||
| 99 | ; Don't change this without consulting "sel.inc", and the | ||
| 100 | ; routines which initialise the gdt. | ||
| 101 | ; | ||
| 102 | |||
| 103 | GDT SEGMENT | ||
| 104 | |||
| 105 | gdtstart label byte ; label for everyone to refer to the GDT | ||
| 106 | |||
| 107 | GDT_ENTRY 0, 0, 1, 0 ; null selector | ||
| 108 | GDT_ENTRY 0, 0, 0, D_DATA0 ; GDT alias | ||
| 109 | GDT_ENTRY 0, 0, 0, D_DATA0 ; IDT alias | ||
| 110 | GDT_ENTRY 0, 0, 0, D_LDT0 ; LDT | ||
| 111 | GDT_ENTRY 0, 0, 0, D_DATA0 ; LDT alias | ||
| 112 | GDT_ENTRY 0, 0, 0, D_386TSS0 ; TSS | ||
| 113 | GDT_ENTRY 0, 0, 0, D_DATA0 ; TSS alias | ||
| 114 | GDT_ENTRY 0, 0, <400h>, D_DATA3 ; Real Mode IDT | ||
| 115 | GDT_ENTRY 400h, 0, <300h>, D_DATA0 ; ROM Data | ||
| 116 | GDT_ENTRY 0, 0, 0, D_CODE0 ; VDM Code | ||
| 117 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Data | ||
| 118 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Stack | ||
| 119 | GDT_ENTRY 0, 0bh, 1000h, D_DATA0 ; Mono Display | ||
| 120 | GDT_ENTRY 8000h, 0bh, 4000h, D_DATA0 ; Colour Disp | ||
| 121 | GDT_ENTRY 0, 0ah, 0, D_DATA0 ; EGA Low | ||
| 122 | GDT_ENTRY 0, 0ch, 0, D_DATA0 ; EGA High | ||
| 123 | GDT_ENTRY 800h, 0, 66h, D_DATA0 ; LOADALL | ||
| 124 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 1 | ||
| 125 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 2 | ||
| 126 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 3 | ||
| 127 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 4 | ||
| 128 | GDT_ENTRY 0, 0, 0, 0 ; debugger work 5 | ||
| 129 | GDT_ENTRY 0, 0, 0, 0 ; debugger work (Addresses all memory) | ||
| 130 | GDT_ENTRY 0, 0, 0, 0 ; general work | ||
| 131 | GDT_ENTRY 0, 0, 0, 0 ; general work | ||
| 132 | GDT_ENTRY 0, 0, 0, D_CODE0 ; maps CODE segment | ||
| 133 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VM1_GSEL - vm trap scratch | ||
| 134 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VM2_GSEL - vm trap scratch | ||
| 135 | GDT_ENTRY 0, 0, 0, D_DATA0 ; MBSRC_GSEL - move blk scratch | ||
| 136 | GDT_ENTRY 0, 0, 0, D_DATA0 ; MBTAR_GSEL - move blk scratch | ||
| 137 | GDT_ENTRY 0, 0, 0, D_DATA0 ; PAGET_GSEL - page table area | ||
| 138 | GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Code - Data Alias | ||
| 139 | GDT_ENTRY 0, 0, 0, D_DATA0 ; EMM1 - EMM scratch selector | ||
| 140 | GDT_ENTRY 0, 0, 0, D_DATA0 ; EMM2 - EMM scratch selector | ||
| 141 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM0 entry | ||
| 142 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM1 entry | ||
| 143 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM2 entry | ||
| 144 | GDT_ENTRY 0, 0, 0, D_DATA0 ; OEM3 entry | ||
| 145 | GDT_ENTRY 0, 0, 0, D_DATA0 ; USER1 entry | ||
| 146 | |||
| 147 | public GDTLEN | ||
| 148 | GDTLEN equ $ - gdtstart | ||
| 149 | |||
| 150 | GDT ENDS | ||
| 151 | |||
| 152 | |||
| 153 | ;*** TSS for protected Mode | ||
| 154 | ; | ||
| 155 | ; This is the VDM TSS. We only use one, for loading | ||
| 156 | ; SS:SP on privilige transitions. We don't use all | ||
| 157 | ; the 286 task switching stuff. | ||
| 158 | ; | ||
| 159 | ; | ||
| 160 | |||
| 161 | TSS segment | ||
| 162 | ; | ||
| 163 | TssArea TSS386STRUC <> | ||
| 164 | ; | ||
| 165 | ; I/O Bit Map for Virtual Mode I/O trapping | ||
| 166 | ; | ||
| 167 | public IOBitMap | ||
| 168 | IOBitMap label byte | ||
| 169 | db 2000h dup (0) ; initialize all ports to NO trapping | ||
| 170 | db 0FFh ; last byte is all 1's | ||
| 171 | |||
| 172 | public TSSLEN | ||
| 173 | TSSLEN equ $ - tss | ||
| 174 | |||
| 175 | TSS ends | ||
| 176 | |||
| 177 | ;*** IDT for protected mode | ||
| 178 | ; | ||
| 179 | ; This is the protected mode interrupt descriptor table. | ||
| 180 | ; | ||
| 181 | ; The first 78h entries are defined. Only processor exceptions and | ||
| 182 | ; hardware interrupts are fielded through the PM IDT. Since the | ||
| 183 | ; gate DPLs are < 3, all software INTs are funneled through INT 13 | ||
| 184 | ; (GP exception) and emulated. Note that Null IDT entries and limit | ||
| 185 | ; exceptions produce the same results (GP error code) as DPL faults, | ||
| 186 | ; so we can use a truncated IDT. This assumes no one is reprogramming | ||
| 187 | ; the 8259s base vector for some reason - don't know of any DOS apps | ||
| 188 | ; that do this. | ||
| 189 | ; | ||
| 190 | IDT SEGMENT | ||
| 191 | |||
| 192 | idtstart label byte | ||
| 193 | |||
| 194 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap00>,D_386INT0 ; 00 Divide Error | ||
| 195 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap01>,D_386INT0 ; 01 Debug | ||
| 196 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap02>,D_386INT0 ; 02 NMI/287 Error | ||
| 197 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap03>,D_386INT0 ; 03 Breakpoint | ||
| 198 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap04>,D_386INT0 ; 04 INTO | ||
| 199 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap05>,D_386INT0 ; 05 BOUND/Print Screen | ||
| 200 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap06>,D_386INT0 ; 06 Invalid Opcode | ||
| 201 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap07>,D_386INT0 ; 07 287 Not Available | ||
| 202 | |||
| 203 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap08>,D_386INT0 ; 08 Double Exception/Timer | ||
| 204 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap09>,D_386INT0 ; 09 (not on 386)/Keyboard | ||
| 205 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0a>,D_386INT0 ; 0A Invalid TSS/Cascade | ||
| 206 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0b>,D_386INT0 ; 0B Segment Not Present/COM2 | ||
| 207 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0c>,D_386INT0 ; 0C Stack Fault/COM1 | ||
| 208 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0d>,D_386INT0 ; 0D General Protection/LPT2 | ||
| 209 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0e>,D_386INT0 ; 0E Page Fault/Diskette | ||
| 210 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap0F>,D_386INT0 ; 0F Intel Reserved/LPT1 | ||
| 211 | |||
| 212 | IDT_ENTRY 0, 0, 0 ; 10 [287 Error]/Video INT (This exception | ||
| 213 | ; cannot occur on AT architecture) | ||
| 214 | IDT_ENTRY 0, 0, 0 ; 11 Equipment Check | ||
| 215 | IDT_ENTRY 0, 0, 0 ; 12 Memory Size | ||
| 216 | IDT_ENTRY 0, 0, 0 ; 13 Disk INT | ||
| 217 | IDT_ENTRY 0, 0, 0 ; 14 RS232 | ||
| 218 | IDT_ENTRY 0, 0, 0 ; 15 Post&Wait, mov_blk via GP fault | ||
| 219 | IDT_ENTRY 0, 0, 0 ; 16 Keyboard | ||
| 220 | IDT_ENTRY 0, 0, 0 ; 17 Printer | ||
| 221 | |||
| 222 | IDT_ENTRY 0, 0, 0 ; 18 Resident BASIC | ||
| 223 | IDT_ENTRY 0, 0, 0 ; 19 Bootstrap | ||
| 224 | IDT_ENTRY 0, 0, 0 ; 1A Time of Day | ||
| 225 | IDT_ENTRY 0, 0, 0 ; 1B Break | ||
| 226 | IDT_ENTRY 0, 0, 0 ; 1C Timer Tick | ||
| 227 | IDT_ENTRY 0, 0, 0 ; 1D Ptr to Video Param | ||
| 228 | IDT_ENTRY 0, 0, 0 ; 1E Ptr to Disk Params | ||
| 229 | IDT_ENTRY 0, 0, 0 ; 1F Ptr to Graphics | ||
| 230 | |||
| 231 | IDT_ENTRY 0, 0, 0 ; 20 DOS | ||
| 232 | IDT_ENTRY 0, 0, 0 ; 21 DOS | ||
| 233 | IDT_ENTRY 0, 0, 0 ; 22 DOS | ||
| 234 | IDT_ENTRY 0, 0, 0 ; 23 DOS | ||
| 235 | IDT_ENTRY 0, 0, 0 ; 24 DOS | ||
| 236 | IDT_ENTRY 0, 0, 0 ; 25 DOS | ||
| 237 | IDT_ENTRY 0, 0, 0 ; 26 DOS | ||
| 238 | IDT_ENTRY 0, 0, 0 ; 27 DOS | ||
| 239 | |||
| 240 | IDT_ENTRY 0, 0, 0 ; 28 DOS | ||
| 241 | IDT_ENTRY 0, 0, 0 ; 29 DOS | ||
| 242 | IDT_ENTRY 0, 0, 0 ; 2A DOS | ||
| 243 | IDT_ENTRY 0, 0, 0 ; 2B DOS | ||
| 244 | IDT_ENTRY 0, 0, 0 ; 2C DOS | ||
| 245 | IDT_ENTRY 0, 0, 0 ; 2D DOS | ||
| 246 | IDT_ENTRY 0, 0, 0 ; 2E DOS | ||
| 247 | IDT_ENTRY 0, 0, 0 ; 2F DOS | ||
| 248 | |||
| 249 | IDT_ENTRY 0, 0, 0 ; 30 DOS | ||
| 250 | IDT_ENTRY 0, 0, 0 ; 31 DOS | ||
| 251 | IDT_ENTRY 0, 0, 0 ; 32 DOS | ||
| 252 | IDT_ENTRY 0, 0, 0 ; 33 DOS | ||
| 253 | IDT_ENTRY 0, 0, 0 ; 34 DOS | ||
| 254 | IDT_ENTRY 0, 0, 0 ; 35 DOS | ||
| 255 | IDT_ENTRY 0, 0, 0 ; 36 DOS | ||
| 256 | IDT_ENTRY 0, 0, 0 ; 37 DOS | ||
| 257 | |||
| 258 | IDT_ENTRY 0, 0, 0 ; 38 DOS | ||
| 259 | IDT_ENTRY 0, 0, 0 ; 39 DOS | ||
| 260 | IDT_ENTRY 0, 0, 0 ; 3A DOS | ||
| 261 | IDT_ENTRY 0, 0, 0 ; 3B DOS | ||
| 262 | IDT_ENTRY 0, 0, 0 ; 3C DOS | ||
| 263 | IDT_ENTRY 0, 0, 0 ; 3D DOS | ||
| 264 | IDT_ENTRY 0, 0, 0 ; 3E DOS | ||
| 265 | IDT_ENTRY 0, 0, 0 ; 3F DOS | ||
| 266 | |||
| 267 | IDT_ENTRY 0, 0, 0 ; 40 Reserved | ||
| 268 | IDT_ENTRY 0, 0, 0 ; 41 Reserved | ||
| 269 | IDT_ENTRY 0, 0, 0 ; 42 Reserved | ||
| 270 | IDT_ENTRY 0, 0, 0 ; 43 Reserved | ||
| 271 | IDT_ENTRY 0, 0, 0 ; 44 Reserved | ||
| 272 | IDT_ENTRY 0, 0, 0 ; 45 Reserved | ||
| 273 | IDT_ENTRY 0, 0, 0 ; 46 Reserved | ||
| 274 | IDT_ENTRY 0, 0, 0 ; 47 Reserved | ||
| 275 | |||
| 276 | IDT_ENTRY 0, 0, 0 ; 48 Reserved | ||
| 277 | IDT_ENTRY 0, 0, 0 ; 49 Reserved | ||
| 278 | IDT_ENTRY 0, 0, 0 ; 4A Reserved | ||
| 279 | IDT_ENTRY 0, 0, 0 ; 4B Reserved | ||
| 280 | IDT_ENTRY 0, 0, 0 ; 4C Reserved | ||
| 281 | IDT_ENTRY 0, 0, 0 ; 4D Reserved | ||
| 282 | IDT_ENTRY 0, 0, 0 ; 4E Reserved | ||
| 283 | IDT_ENTRY 0, 0, 0 ; 4F Reserved | ||
| 284 | |||
| 285 | ; | ||
| 286 | ; The following table entries assume the master 8259 base vector has been | ||
| 287 | ; set up to 50h. | ||
| 288 | ; | ||
| 289 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap50>,D_386INT0 ; 50 Timer Interrupt | ||
| 290 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap51>,D_386INT0 ; 51 Keyboard Interrupt | ||
| 291 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap52>,D_386INT0 ; 52 Misc peripheral Interrupt | ||
| 292 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap53>,D_386INT0 ; 53 COM2 | ||
| 293 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap54>,D_386INT0 ; 54 COM1 | ||
| 294 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap55>,D_386INT0 ; 55 2nd Parallel | ||
| 295 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap56>,D_386INT0 ; 56 Diskette Interrupt | ||
| 296 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap57>,D_386INT0 ; 57 1st Parallel | ||
| 297 | |||
| 298 | IDT_ENTRY 0, 0, 0 ; 58 Reserved | ||
| 299 | IDT_ENTRY 0, 0, 0 ; 59 Reserved | ||
| 300 | IDT_ENTRY 0, 0, 0 ; 5A Reserved | ||
| 301 | IDT_ENTRY 0, 0, 0 ; 5B Reserved | ||
| 302 | IDT_ENTRY 0, 0, 0 ; 5C Reserved | ||
| 303 | IDT_ENTRY 0, 0, 0 ; 5D Reserved | ||
| 304 | IDT_ENTRY 0, 0, 0 ; 5E Reserved | ||
| 305 | IDT_ENTRY 0, 0, 0 ; 5F Reserved | ||
| 306 | |||
| 307 | IDT_ENTRY 0, 0, 0 ; 60 User Programs | ||
| 308 | IDT_ENTRY 0, 0, 0 ; 61 User Programs | ||
| 309 | IDT_ENTRY 0, 0, 0 ; 62 User Programs | ||
| 310 | IDT_ENTRY 0, 0, 0 ; 63 User Programs | ||
| 311 | IDT_ENTRY 0, 0, 0 ; 64 User Programs | ||
| 312 | IDT_ENTRY 0, 0, 0 ; 65 User Programs | ||
| 313 | IDT_ENTRY 0, 0, 0 ; 66 User Programs | ||
| 314 | ;;;IDT_ENTRY 0, 0, 0 ; 67 User Programs | ||
| 315 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:EMM_pEntry>,D_386INT3 ; 67 ELIM | ||
| 316 | |||
| 317 | IDT_ENTRY 0, 0, 0 ; 68 Not Used | ||
| 318 | IDT_ENTRY 0, 0, 0 ; 69 Not Used | ||
| 319 | IDT_ENTRY 0, 0, 0 ; 6A Not Used | ||
| 320 | IDT_ENTRY 0, 0, 0 ; 6B Not Used | ||
| 321 | IDT_ENTRY 0, 0, 0 ; 6C Not Used | ||
| 322 | IDT_ENTRY 0, 0, 0 ; 6D Not Used | ||
| 323 | IDT_ENTRY 0, 0, 0 ; 6E Not Used | ||
| 324 | IDT_ENTRY 0, 0, 0 ; 6F Not Used | ||
| 325 | |||
| 326 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap70>,D_386INT0 ; 70 IRQ8 - Real Time Clock | ||
| 327 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap71>,D_386INT0 ; 71 IRQ9 | ||
| 328 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap72>,D_386INT0 ; 72 IRQ10 | ||
| 329 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap73>,D_386INT0 ; 73 IRQ11 | ||
| 330 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap74>,D_386INT0 ; 74 IRQ12 | ||
| 331 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap75>,D_386INT0 ; 75 IRQ13 - 287 error | ||
| 332 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap76>,D_386INT0 ; 76 IRQ14 - Fixed disk | ||
| 333 | IDT_ENTRY VDMC_GSEL,<offset _TEXT:vm_trap77>,D_386INT0 ; 77 IRQ15 | ||
| 334 | |||
| 335 | public IDTLEN | ||
| 336 | idtlen equ this byte - idtstart | ||
| 337 | |||
| 338 | IDT ends | ||
| 339 | |||
| 340 | PAGESEG SEGMENT | ||
| 341 | ;*** Page Tables Area | ||
| 342 | ; | ||
| 343 | ; This area is used for the page directory and page tables | ||
| 344 | ; | ||
| 345 | |||
| 346 | public P_TABLE_CNT | ||
| 347 | P_TABLE_CNT equ 5 ; # of page tables | ||
| 348 | |||
| 349 | public Page_Area | ||
| 350 | Page_Area label byte | ||
| 351 | db (2+P_TABLE_CNT) * P_SIZE dup (0) ; enough for page dir & | ||
| 352 | ; tables after page | ||
| 353 | ; alignment. | ||
| 354 | PAGESEG ENDS | ||
| 355 | |||
| 356 | END | ||
| 357 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/TRAPDEF.ASM b/v4.0/src/MEMM/MEMM/TRAPDEF.ASM new file mode 100644 index 0000000..b82f661 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/TRAPDEF.ASM | |||
| @@ -0,0 +1,469 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title TRAPDEF.ASM - I/O trap Dispatch table | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: TRAPDEF.ASM - I/O trap Dispatch table | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: July 1, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 08/11/86 Split from IOTrap.asm | ||
| 27 | ; | ||
| 28 | ; 7/26/88 Added Trap handler entries for DMA ports on Channel 4 | ||
| 29 | ; - Jaywant H Bharadwaj | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ; | ||
| 33 | .lfcond ; list false conditionals | ||
| 34 | .386p | ||
| 35 | page | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; P U B L I C D E C L A R A T I O N S | ||
| 38 | ;****************************************************************************** | ||
| 39 | ; | ||
| 40 | public IOTrap_Tab ; dispatches I/O trap handlers | ||
| 41 | public IOT_BadT ; Unknown port trap routine | ||
| 42 | public IOT_OEM ; OEM specific port emulation | ||
| 43 | |||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; L O C A L C O N S T A N T S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | ; % - how many of these are actually needed? | ||
| 50 | ; % - Need any includes from Win/386 DMA code - trapdef.asm ? | ||
| 51 | |||
| 52 | include VDMseg.inc | ||
| 53 | include VDMsel.inc | ||
| 54 | include desc.inc | ||
| 55 | include elim.inc | ||
| 56 | include page.inc | ||
| 57 | include oemdep.inc | ||
| 58 | include instr386.inc | ||
| 59 | include vm386.inc | ||
| 60 | ; | ||
| 61 | ;****************************************************************************** | ||
| 62 | ; E X T E R N A L R E F E R E N C E S | ||
| 63 | ;****************************************************************************** | ||
| 64 | ; | ||
| 65 | |||
| 66 | _DATA segment | ||
| 67 | ;extrn _map_size:byte ; # of mapping registers used | ||
| 68 | ;extrn LIMP_Addr:word | ||
| 69 | _DATA ends | ||
| 70 | |||
| 71 | _TEXT segment | ||
| 72 | ; | ||
| 73 | extrn RRP_Handler:near | ||
| 74 | extrn A20_Handler:near ; Kybd Data port - A20 watch | ||
| 75 | extrn DMABase0:near ; DMA base register for Channel 0 | ||
| 76 | extrn DMABase1:near ; DMA base register for Channel 1 | ||
| 77 | extrn DMABase2:near ; DMA base register for Channel 2 | ||
| 78 | extrn DMABase3:near ; DMA base register for Channel 3 | ||
| 79 | extrn DMABase5:near ; DMA base register for Channel 5 | ||
| 80 | extrn DMABase6:near ; DMA base register for Channel 6 | ||
| 81 | extrn DMABase7:near ; DMA base register for Channel 7 | ||
| 82 | extrn DMACnt0:near ; DMA count register for Channel 0 | ||
| 83 | extrn DMACnt1:near ; DMA count register for Channel 1 | ||
| 84 | extrn DMACnt2:near ; DMA count register for Channel 2 | ||
| 85 | extrn DMACnt3:near ; DMA count register for Channel 3 | ||
| 86 | extrn DMACnt5:near ; DMA count register for Channel 5 | ||
| 87 | extrn DMACnt6:near ; DMA count register for Channel 6 | ||
| 88 | extrn DMACnt7:near ; DMA count register for Channel 7 | ||
| 89 | extrn DMAPg0:near ; DMA page register for Channel 0 | ||
| 90 | extrn DMAPg1:near ; DMA page register for Channel 1 | ||
| 91 | extrn DMAPg2:near ; DMA page register for Channel 2 | ||
| 92 | extrn DMAPg3:near ; DMA page register for Channel 3 | ||
| 93 | extrn DMAPg5:near ; DMA page register for Channel 5 | ||
| 94 | extrn DMAPg6:near ; DMA page register for Channel 6 | ||
| 95 | extrn DMAPg7:near ; DMA page register for Channel 7 | ||
| 96 | extrn DMAClrFF1:near ; clear flip-flop cmd for channels 0-3 | ||
| 97 | extrn DMAClrFF2:near ; clear flip-flop cmd for channels 5-7 | ||
| 98 | extrn DMAMode1:near ; Mode register for channels 0-3 | ||
| 99 | extrn DMAMode2:near ; Mode register for channels 4-7 | ||
| 100 | |||
| 101 | _TEXT ends | ||
| 102 | |||
| 103 | ;****************************************************************************** | ||
| 104 | ; S E G M E N T D E F I N I T I O N | ||
| 105 | ;****************************************************************************** | ||
| 106 | |||
| 107 | ; | ||
| 108 | ;------------------------------------------------------------------------------ | ||
| 109 | _TEXT segment | ||
| 110 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 111 | ; | ||
| 112 | ; IOTrapTab | ||
| 113 | ; One entry per port in the I/O space from 00h to FFh. | ||
| 114 | ; Note that ports not specifically mapped otherwise(by IOT_OEM or | ||
| 115 | ; LIM emulation and whose least significant 10 bits are less than | ||
| 116 | ; 100h are also dispatched through this table(upper 6 bits assumed to | ||
| 117 | ; be intended as zero since some earlier systems only had 10 bits of | ||
| 118 | ; I/O addressing). | ||
| 119 | ; | ||
| 120 | IOTrap_Tab label word | ||
| 121 | dw offset _TEXT:DMAbase0 ; 0 DMA base register for Channel 0 | ||
| 122 | dw offset _TEXT:DMACnt0 ; 1 DMA count register for Channel 0 | ||
| 123 | dw offset _TEXT:DMABase1 ; 2 DMA base register for Channel 1 | ||
| 124 | dw offset _TEXT:DMACnt1 ; 3 DMA count register for Channel 1 | ||
| 125 | dw offset _TEXT:DMABase2 ; 4 DMA base register for Channel 2 | ||
| 126 | dw offset _TEXT:DMACnt2 ; 5 DMA count register for Channel 2 | ||
| 127 | dw offset _TEXT:DMABase3 ; 6 DMA base register for Channel 3 | ||
| 128 | dw offset _TEXT:DMACnt3 ; 7 DMA count register for Channel 3 | ||
| 129 | dw offset _TEXT:IOT_BadT ; 8 | ||
| 130 | dw offset _TEXT:IOT_BadT ; 9 | ||
| 131 | dw offset _TEXT:IOT_BadT ; a | ||
| 132 | dw offset _TEXT:DMAMode1 ; b DMA Mode Register for for Ch 0-3 | ||
| 133 | dw offset _TEXT:DMAClrFF1 ; c clear flip-flop cmd for channels 0-3 | ||
| 134 | dw offset _TEXT:IOT_BadT ; d | ||
| 135 | dw offset _TEXT:IOT_BadT ; e | ||
| 136 | dw offset _TEXT:IOT_BadT ; f | ||
| 137 | dw offset _TEXT:IOT_BadT ; 10 | ||
| 138 | dw offset _TEXT:IOT_BadT ; 11 | ||
| 139 | dw offset _TEXT:IOT_BadT ; 12 | ||
| 140 | dw offset _TEXT:IOT_BadT ; 13 | ||
| 141 | dw offset _TEXT:IOT_BadT ; 14 | ||
| 142 | dw offset _TEXT:IOT_BadT ; 15 | ||
| 143 | dw offset _TEXT:IOT_BadT ; 16 | ||
| 144 | dw offset _TEXT:IOT_BadT ; 17 | ||
| 145 | dw offset _TEXT:IOT_BadT ; 18 | ||
| 146 | dw offset _TEXT:IOT_BadT ; 19 | ||
| 147 | dw offset _TEXT:IOT_BadT ; 1a | ||
| 148 | dw offset _TEXT:IOT_BadT ; 1b | ||
| 149 | dw offset _TEXT:IOT_BadT ; 1c | ||
| 150 | dw offset _TEXT:IOT_BadT ; 1d | ||
| 151 | dw offset _TEXT:IOT_BadT ; 1e | ||
| 152 | dw offset _TEXT:IOT_BadT ; 1f | ||
| 153 | dw offset _TEXT:IOT_BadT ; 20 | ||
| 154 | dw offset _TEXT:IOT_BadT ; 21 | ||
| 155 | dw offset _TEXT:IOT_BadT ; 22 | ||
| 156 | dw offset _TEXT:IOT_BadT ; 23 | ||
| 157 | dw offset _TEXT:IOT_BadT ; 24 | ||
| 158 | dw offset _TEXT:IOT_BadT ; 25 | ||
| 159 | dw offset _TEXT:IOT_BadT ; 26 | ||
| 160 | dw offset _TEXT:IOT_BadT ; 27 | ||
| 161 | dw offset _TEXT:IOT_BadT ; 28 | ||
| 162 | dw offset _TEXT:IOT_BadT ; 29 | ||
| 163 | dw offset _TEXT:IOT_BadT ; 2a | ||
| 164 | dw offset _TEXT:IOT_BadT ; 2b | ||
| 165 | dw offset _TEXT:IOT_BadT ; 2c | ||
| 166 | dw offset _TEXT:IOT_BadT ; 2d | ||
| 167 | dw offset _TEXT:IOT_BadT ; 2e | ||
| 168 | dw offset _TEXT:IOT_BadT ; 2f | ||
| 169 | dw offset _TEXT:IOT_BadT ; 30 | ||
| 170 | dw offset _TEXT:IOT_BadT ; 31 | ||
| 171 | dw offset _TEXT:IOT_BadT ; 32 | ||
| 172 | dw offset _TEXT:IOT_BadT ; 33 | ||
| 173 | dw offset _TEXT:IOT_BadT ; 34 | ||
| 174 | dw offset _TEXT:IOT_BadT ; 35 | ||
| 175 | dw offset _TEXT:IOT_BadT ; 36 | ||
| 176 | dw offset _TEXT:IOT_BadT ; 37 | ||
| 177 | dw offset _TEXT:IOT_BadT ; 38 | ||
| 178 | dw offset _TEXT:IOT_BadT ; 39 | ||
| 179 | dw offset _TEXT:IOT_BadT ; 3a | ||
| 180 | dw offset _TEXT:IOT_BadT ; 3b | ||
| 181 | dw offset _TEXT:IOT_BadT ; 3c | ||
| 182 | dw offset _TEXT:IOT_BadT ; 3d | ||
| 183 | dw offset _TEXT:IOT_BadT ; 3e | ||
| 184 | dw offset _TEXT:IOT_BadT ; 3f | ||
| 185 | dw offset _TEXT:IOT_BadT ; 40 | ||
| 186 | dw offset _TEXT:IOT_BadT ; 41 | ||
| 187 | dw offset _TEXT:IOT_BadT ; 42 | ||
| 188 | dw offset _TEXT:IOT_BadT ; 43 | ||
| 189 | dw offset _TEXT:IOT_BadT ; 44 | ||
| 190 | dw offset _TEXT:IOT_BadT ; 45 | ||
| 191 | dw offset _TEXT:IOT_BadT ; 46 | ||
| 192 | dw offset _TEXT:IOT_BadT ; 47 | ||
| 193 | dw offset _TEXT:IOT_BadT ; 48 | ||
| 194 | dw offset _TEXT:IOT_BadT ; 49 | ||
| 195 | dw offset _TEXT:IOT_BadT ; 4a | ||
| 196 | dw offset _TEXT:IOT_BadT ; 4b | ||
| 197 | dw offset _TEXT:IOT_BadT ; 4c | ||
| 198 | dw offset _TEXT:IOT_BadT ; 4d | ||
| 199 | dw offset _TEXT:IOT_BadT ; 4e | ||
| 200 | dw offset _TEXT:IOT_BadT ; 4f | ||
| 201 | dw offset _TEXT:IOT_BadT ; 50 | ||
| 202 | dw offset _TEXT:IOT_BadT ; 51 | ||
| 203 | dw offset _TEXT:IOT_BadT ; 52 | ||
| 204 | dw offset _TEXT:IOT_BadT ; 53 | ||
| 205 | dw offset _TEXT:IOT_BadT ; 54 | ||
| 206 | dw offset _TEXT:IOT_BadT ; 55 | ||
| 207 | dw offset _TEXT:IOT_BadT ; 56 | ||
| 208 | dw offset _TEXT:IOT_BadT ; 57 | ||
| 209 | dw offset _TEXT:IOT_BadT ; 58 | ||
| 210 | dw offset _TEXT:IOT_BadT ; 59 | ||
| 211 | dw offset _TEXT:IOT_BadT ; 5a | ||
| 212 | dw offset _TEXT:IOT_BadT ; 5b | ||
| 213 | dw offset _TEXT:IOT_BadT ; 5c | ||
| 214 | dw offset _TEXT:IOT_BadT ; 5d | ||
| 215 | dw offset _TEXT:IOT_BadT ; 5e | ||
| 216 | dw offset _TEXT:IOT_BadT ; 5f | ||
| 217 | dw offset _TEXT:A20_Handler ; A20 watch on kybd data port | ||
| 218 | dw offset _TEXT:IOT_BadT ; 61 | ||
| 219 | dw offset _TEXT:IOT_BadT ; 62 | ||
| 220 | dw offset _TEXT:IOT_BadT ; 63 | ||
| 221 | dw offset _TEXT:A20_Handler ; A20 watch on kybd cmd port | ||
| 222 | dw offset _TEXT:IOT_BadT ; 65 | ||
| 223 | dw offset _TEXT:IOT_BadT ; 66 | ||
| 224 | dw offset _TEXT:IOT_BadT ; 67 | ||
| 225 | dw offset _TEXT:IOT_BadT ; 68 | ||
| 226 | dw offset _TEXT:IOT_BadT ; 69 | ||
| 227 | dw offset _TEXT:IOT_BadT ; 6a | ||
| 228 | dw offset _TEXT:IOT_BadT ; 6b | ||
| 229 | dw offset _TEXT:IOT_BadT ; 6c | ||
| 230 | dw offset _TEXT:IOT_BadT ; 6d | ||
| 231 | dw offset _TEXT:IOT_BadT ; 6e | ||
| 232 | dw offset _TEXT:IOT_BadT ; 6f | ||
| 233 | dw offset _TEXT:IOT_BadT ; 70 | ||
| 234 | dw offset _TEXT:IOT_BadT ; 71 | ||
| 235 | dw offset _TEXT:IOT_BadT ; 72 | ||
| 236 | dw offset _TEXT:IOT_BadT ; 73 | ||
| 237 | dw offset _TEXT:IOT_BadT ; 74 | ||
| 238 | dw offset _TEXT:IOT_BadT ; 75 | ||
| 239 | dw offset _TEXT:IOT_BadT ; 76 | ||
| 240 | dw offset _TEXT:IOT_BadT ; 77 | ||
| 241 | dw offset _TEXT:IOT_BadT ; 78 | ||
| 242 | dw offset _TEXT:IOT_BadT ; 79 | ||
| 243 | dw offset _TEXT:IOT_BadT ; 7a | ||
| 244 | dw offset _TEXT:IOT_BadT ; 7b | ||
| 245 | dw offset _TEXT:IOT_BadT ; 7c | ||
| 246 | dw offset _TEXT:IOT_BadT ; 7d | ||
| 247 | dw offset _TEXT:IOT_BadT ; 7e | ||
| 248 | dw offset _TEXT:IOT_BadT ; 7f | ||
| 249 | dw offset _TEXT:IOT_BadT ; 80 | ||
| 250 | dw offset _TEXT:DMAPg2 ; 81 DMA page register for Channel 2 | ||
| 251 | dw offset _TEXT:DMAPg3 ; 82 DMA page register for Channel 3 | ||
| 252 | dw offset _TEXT:DMAPg1 ; 83 DMA page register for Channel 1 | ||
| 253 | dw offset _TEXT:RRP_Handler ; return to real port | ||
| 254 | dw offset _TEXT:RRP_Handler ; return to real port | ||
| 255 | dw offset _TEXT:IOT_BadT ; 86 | ||
| 256 | dw offset _TEXT:DMAPg0 ; 87 DMA page register for Channel 0 | ||
| 257 | dw offset _TEXT:IOT_BadT ; 88 | ||
| 258 | dw offset _TEXT:DMAPg6 ; 89 DMA page register for Channel 6 | ||
| 259 | dw offset _TEXT:DMAPg7 ; 8a DMA page register for Channel 7 | ||
| 260 | dw offset _TEXT:DMAPg5 ; 8b DMA page register for Channel 5 | ||
| 261 | dw offset _TEXT:IOT_BadT ; 8c | ||
| 262 | dw offset _TEXT:IOT_BadT ; 8d | ||
| 263 | dw offset _TEXT:IOT_BadT ; 8e | ||
| 264 | dw offset _TEXT:IOT_BadT ; 8f | ||
| 265 | dw offset _TEXT:IOT_BadT ; 90 | ||
| 266 | dw offset _TEXT:DMAPg2 ; 91 DMA page register for Channel 2 | ||
| 267 | dw offset _TEXT:DMAPg3 ; 92 DMA page register for Channel 3 | ||
| 268 | dw offset _TEXT:DMAPg1 ; 93 DMA page register for Channel 1 | ||
| 269 | dw offset _TEXT:IOT_BadT ; 94 | ||
| 270 | dw offset _TEXT:IOT_BadT ; 95 | ||
| 271 | dw offset _TEXT:IOT_BadT ; 96 | ||
| 272 | dw offset _TEXT:IOT_BadT ; 97 DMA page register for Channel 0 | ||
| 273 | dw offset _TEXT:IOT_BadT ; 98 | ||
| 274 | dw offset _TEXT:DMAPg6 ; 99 DMA page register for Channel 6 | ||
| 275 | dw offset _TEXT:DMAPg7 ; 9a DMA page register for Channel 7 | ||
| 276 | dw offset _TEXT:DMAPg5 ; 9b DMA page register for Channel 5 | ||
| 277 | dw offset _TEXT:IOT_BadT ; 9c | ||
| 278 | dw offset _TEXT:IOT_BadT ; 9d | ||
| 279 | dw offset _TEXT:IOT_BadT ; 9e | ||
| 280 | dw offset _TEXT:IOT_BadT ; 9f | ||
| 281 | dw offset _TEXT:IOT_BadT ; a0 | ||
| 282 | dw offset _TEXT:IOT_BadT ; a1 | ||
| 283 | dw offset _TEXT:IOT_BadT ; a2 | ||
| 284 | dw offset _TEXT:IOT_BadT ; a3 | ||
| 285 | dw offset _TEXT:IOT_BadT ; a4 | ||
| 286 | dw offset _TEXT:IOT_BadT ; a5 | ||
| 287 | dw offset _TEXT:IOT_BadT ; a6 | ||
| 288 | dw offset _TEXT:IOT_BadT ; a7 | ||
| 289 | dw offset _TEXT:IOT_BadT ; a8 | ||
| 290 | dw offset _TEXT:IOT_BadT ; a9 | ||
| 291 | dw offset _TEXT:IOT_BadT ; aa | ||
| 292 | dw offset _TEXT:IOT_BadT ; ab | ||
| 293 | dw offset _TEXT:IOT_BadT ; ac | ||
| 294 | dw offset _TEXT:IOT_BadT ; ad | ||
| 295 | dw offset _TEXT:IOT_BadT ; ae | ||
| 296 | dw offset _TEXT:IOT_BadT ; af | ||
| 297 | dw offset _TEXT:IOT_BadT ; b0 | ||
| 298 | dw offset _TEXT:IOT_BadT ; b1 | ||
| 299 | dw offset _TEXT:IOT_BadT ; b2 | ||
| 300 | dw offset _TEXT:IOT_BadT ; b3 | ||
| 301 | dw offset _TEXT:IOT_BadT ; b4 | ||
| 302 | dw offset _TEXT:IOT_BadT ; b5 | ||
| 303 | dw offset _TEXT:IOT_BadT ; b6 | ||
| 304 | dw offset _TEXT:IOT_BadT ; b7 | ||
| 305 | dw offset _TEXT:IOT_BadT ; b8 | ||
| 306 | dw offset _TEXT:IOT_BadT ; b9 | ||
| 307 | dw offset _TEXT:IOT_BadT ; ba | ||
| 308 | dw offset _TEXT:IOT_BadT ; bb | ||
| 309 | dw offset _TEXT:IOT_BadT ; bc | ||
| 310 | dw offset _TEXT:IOT_BadT ; bd | ||
| 311 | dw offset _TEXT:IOT_BadT ; be | ||
| 312 | dw offset _TEXT:IOT_BadT ; bf | ||
| 313 | dw offset _TEXT:IOT_BadT ; c0 DMA base register for Channel 4 | ||
| 314 | dw offset _TEXT:IOT_BadT ; c1 | ||
| 315 | dw offset _TEXT:IOT_BadT ; c2 DMA count register for Channel 4 | ||
| 316 | dw offset _TEXT:IOT_BadT ; c3 | ||
| 317 | dw offset _TEXT:DMABase5 ; c4 DMA base register for Channel 5 | ||
| 318 | dw offset _TEXT:IOT_BadT ; c5 | ||
| 319 | dw offset _TEXT:DMACnt5 ; c6 DMA count register for Channel 5 | ||
| 320 | dw offset _TEXT:IOT_BadT ; c7 | ||
| 321 | dw offset _TEXT:DMABase6 ; c8 DMA base register for Channel 6 | ||
| 322 | dw offset _TEXT:IOT_BadT ; c9 | ||
| 323 | dw offset _TEXT:DMACnt6 ; ca DMA count register for Channel 6 | ||
| 324 | dw offset _TEXT:IOT_BadT ; cb | ||
| 325 | dw offset _TEXT:DMABase7 ; cc DMA base register for Channel 7 | ||
| 326 | dw offset _TEXT:IOT_BadT ; cd | ||
| 327 | dw offset _TEXT:DMACnt7 ; ce DMA count register for Channel 7 | ||
| 328 | dw offset _TEXT:IOT_BadT ; cf | ||
| 329 | dw offset _TEXT:IOT_BadT ; d0 | ||
| 330 | dw offset _TEXT:IOT_BadT ; d1 | ||
| 331 | dw offset _TEXT:IOT_BadT ; d2 | ||
| 332 | dw offset _TEXT:IOT_BadT ; d3 | ||
| 333 | dw offset _TEXT:IOT_BadT ; d4 | ||
| 334 | dw offset _TEXT:IOT_BadT ; d5 | ||
| 335 | dw offset _TEXT:DMAMode2 ; d6 DMA Mode Register for channels 4-7 | ||
| 336 | dw offset _TEXT:IOT_BadT ; d7 | ||
| 337 | dw offset _TEXT:DMAClrFF2 ; d8 clear flip-flop cmd for channels 5-7 | ||
| 338 | dw offset _TEXT:IOT_BadT ; d9 | ||
| 339 | dw offset _TEXT:IOT_BadT ; da | ||
| 340 | dw offset _TEXT:IOT_BadT ; db | ||
| 341 | dw offset _TEXT:IOT_BadT ; dc | ||
| 342 | dw offset _TEXT:IOT_BadT ; dd | ||
| 343 | dw offset _TEXT:IOT_BadT ; de | ||
| 344 | dw offset _TEXT:IOT_BadT ; df | ||
| 345 | dw offset _TEXT:IOT_BadT ; e0 | ||
| 346 | dw offset _TEXT:IOT_BadT ; e1 | ||
| 347 | dw offset _TEXT:IOT_BadT ; e2 | ||
| 348 | dw offset _TEXT:IOT_BadT ; e3 | ||
| 349 | dw offset _TEXT:IOT_BadT ; e4 | ||
| 350 | dw offset _TEXT:IOT_BadT ; e5 | ||
| 351 | dw offset _TEXT:IOT_BadT ; e6 | ||
| 352 | dw offset _TEXT:IOT_BadT ; e7 | ||
| 353 | dw offset _TEXT:IOT_BadT ; e8 | ||
| 354 | dw offset _TEXT:IOT_BadT ; e9 | ||
| 355 | dw offset _TEXT:IOT_BadT ; ea | ||
| 356 | dw offset _TEXT:IOT_BadT ; eb | ||
| 357 | dw offset _TEXT:IOT_BadT ; ec | ||
| 358 | dw offset _TEXT:IOT_BadT ; ed | ||
| 359 | dw offset _TEXT:IOT_BadT ; ee | ||
| 360 | dw offset _TEXT:IOT_BadT ; ef | ||
| 361 | dw offset _TEXT:IOT_BadT ; f0 | ||
| 362 | dw offset _TEXT:IOT_BadT ; f1 | ||
| 363 | dw offset _TEXT:IOT_BadT ; f2 | ||
| 364 | dw offset _TEXT:IOT_BadT ; f3 | ||
| 365 | dw offset _TEXT:IOT_BadT ; f4 | ||
| 366 | dw offset _TEXT:IOT_BadT ; f5 | ||
| 367 | dw offset _TEXT:IOT_BadT ; f6 | ||
| 368 | dw offset _TEXT:IOT_BadT ; f7 | ||
| 369 | dw offset _TEXT:IOT_BadT ; f8 | ||
| 370 | dw offset _TEXT:IOT_BadT ; f9 | ||
| 371 | dw offset _TEXT:IOT_BadT ; fa | ||
| 372 | dw offset _TEXT:IOT_BadT ; fb | ||
| 373 | dw offset _TEXT:IOT_BadT ; fc | ||
| 374 | dw offset _TEXT:IOT_BadT ; fd | ||
| 375 | dw offset _TEXT:IOT_BadT ; fe | ||
| 376 | dw offset _TEXT:IOT_BadT ; ff | ||
| 377 | |||
| 378 | ;****************************************************************************** | ||
| 379 | ; IOT_BadT - GP fault on Unknown I/O address | ||
| 380 | ; | ||
| 381 | ; DESCRIPTION: This routine is entered by being in the IOTrap_Tab above | ||
| 382 | ; and also for I/O ports which are not LIM(DMA) ports and are not | ||
| 383 | ; emulated by IOT_OEM routine below and the first 10 bits of the | ||
| 384 | ; address is greater than 100h. Note that only the first 10 bits | ||
| 385 | ; of the port (times 2) is passed in BX. If the entire port | ||
| 386 | ; address is desired, it is available on the stack as the value | ||
| 387 | ; which is popped into DX. | ||
| 388 | ; | ||
| 389 | ; ENTRY: Protected Mode Ring 0 | ||
| 390 | ; return address, DX, DS, return address on stack | ||
| 391 | ; AL = byte to output to port. | ||
| 392 | ; BX == 2 * port address(either 0-1FE or 200-7FE) | ||
| 393 | ; DX == 0 => Emulate input | ||
| 394 | ; <> 0 => Emulate output | ||
| 395 | ; DS = DGROUP | ||
| 396 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 397 | ; | ||
| 398 | ; | ||
| 399 | ; EXIT: Protected Mode Ring 0 | ||
| 400 | ; First return address, pop'd from stack. | ||
| 401 | ; DX and DS restored from stack. | ||
| 402 | ; BX = DX on entry | ||
| 403 | ; STC => I/O NOT emulated. | ||
| 404 | ; | ||
| 405 | ; WARNING:*********** | ||
| 406 | ; This routine is closely allied with IOTrap which is in IOTrap. | ||
| 407 | ; It is assumed that IOTrap puts the stack in a certain state! | ||
| 408 | ; *********** | ||
| 409 | |||
| 410 | ; USED: Flags | ||
| 411 | ; STACK: | ||
| 412 | ;------------------------------------------------------------------------------ | ||
| 413 | ; | ||
| 414 | IOT_BadT proc near | ||
| 415 | pop bx ; dump return address | ||
| 416 | mov bx,dx ; restore BX | ||
| 417 | pop dx ; restore DX(port address) | ||
| 418 | pop ds ; restore DS | ||
| 419 | stc ; port not emulated ! | ||
| 420 | ret ; and return | ||
| 421 | IOT_BadT endp | ||
| 422 | |||
| 423 | ;****************************************************************************** | ||
| 424 | ; IOT_OEM - Handles OEM specific I/O traps | ||
| 425 | ; | ||
| 426 | ; ENTRY: Protected Mode Ring 0 | ||
| 427 | ; AL = byte to output to port. | ||
| 428 | ; DX = port address for I/O. | ||
| 429 | ; SS:BP = points to stack frame on entry to GP fault handler | ||
| 430 | ; BX = 0 => Emulate Input. | ||
| 431 | ; <>0 => Emulate Output. | ||
| 432 | ; DS = DGROUP | ||
| 433 | ; stack: near return to IOTrap, DX, DS, near return from IOTrap | ||
| 434 | ; | ||
| 435 | ; EXIT: Protected Mode Ring 0 | ||
| 436 | ; Either emulate I/O and pop return, DX, DS from stack and RET | ||
| 437 | ; with CF = 1(CF = 0 if I/O is to be ignored!?!?). | ||
| 438 | ; Or just return(no emulation done) | ||
| 439 | ; | ||
| 440 | ; | ||
| 441 | ; WARNING:*********** | ||
| 442 | ; This routine is closely allied with IOTrap. | ||
| 443 | ; It assumes that the stack is in a certain state! | ||
| 444 | ; *********** | ||
| 445 | ; | ||
| 446 | ; | ||
| 447 | ; USED: Flags | ||
| 448 | ; STACK: | ||
| 449 | ;------------------------------------------------------------------------------ | ||
| 450 | IOT_OEM proc near | ||
| 451 | ; cmp dx,???? | ||
| 452 | ; jnz NoEmulation | ||
| 453 | ; or bx,bx | ||
| 454 | ; jnz NoEmulation | ||
| 455 | ; mov al,???? ;emulate input | ||
| 456 | ; pop dx ;remove return | ||
| 457 | ; pop dx ;restore DX | ||
| 458 | ; pop ds ;restore DS | ||
| 459 | ; ret ;return from IOTRAP | ||
| 460 | ; | ||
| 461 | ;NoEmulation: | ||
| 462 | ret ; no emulation | ||
| 463 | IOT_OEM endp | ||
| 464 | |||
| 465 | |||
| 466 | _TEXT ends | ||
| 467 | |||
| 468 | end | ||
| 469 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/UTIL.ASM b/v4.0/src/MEMM/MEMM/UTIL.ASM new file mode 100644 index 0000000..221efdf --- /dev/null +++ b/v4.0/src/MEMM/MEMM/UTIL.ASM | |||
| @@ -0,0 +1,335 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title UTIL - general MEMM utilities | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: UTIL - utilities | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: June 11, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/11/86 Original from i286.asm | ||
| 27 | ; 06/18/86 0.01 in GoVirtual - added code to init VDM state variables | ||
| 28 | ; 06/25/86 0.02 in GoVirtual - more DiagByte state variable. | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 06/29/86 0.02 Changed check code for ROM write protect state | ||
| 31 | ; 07/01/86 0.03 Added call to InitDMA in GoVirtual | ||
| 32 | ; 07/05/86 0.04 Moved code to InitLOCK | ||
| 33 | ; 07/05/86 0.04 Added FarGoVirtual and moved IsReal to PRINT.ASM | ||
| 34 | ; 07/06/86 0.04 Changed assume to DGROUP and moved stack out of DGROUP | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .lfcond ; list false conditionals | ||
| 43 | .386p | ||
| 44 | |||
| 45 | public GoVirtual | ||
| 46 | public FarGoVirtual | ||
| 47 | public SelToSeg | ||
| 48 | |||
| 49 | ;****************************************************************************** | ||
| 50 | ; D E F I N E S | ||
| 51 | ;****************************************************************************** | ||
| 52 | include VDMseg.inc | ||
| 53 | include VDMsel.inc | ||
| 54 | include desc.inc | ||
| 55 | include instr386.inc | ||
| 56 | include oemdep.inc | ||
| 57 | |||
| 58 | FALSE equ 0 | ||
| 59 | TRUE equ not FALSE | ||
| 60 | |||
| 61 | ;****************************************************************************** | ||
| 62 | ; E X T E R N A L R E F E R E N C E S | ||
| 63 | ;****************************************************************************** | ||
| 64 | _DATA SEGMENT | ||
| 65 | |||
| 66 | extrn TEXT_Seg:word ; segment for _TEXT | ||
| 67 | extrn GDT_Seg:word ; segment for GDT | ||
| 68 | extrn TSS_Seg:word ; segment address of TSS | ||
| 69 | extrn Page_Dir:word ; 32-bit address of Page Directory Table | ||
| 70 | |||
| 71 | extrn Active_Status:byte | ||
| 72 | |||
| 73 | _DATA ENDS | ||
| 74 | |||
| 75 | _TEXT SEGMENT | ||
| 76 | |||
| 77 | extrn InitDMA:near ; (elimtrap.asm) | ||
| 78 | extrn EnableA20:near ; (modesw.asm) | ||
| 79 | extrn A20_Trap_Init:near ; (a20trap.asm) | ||
| 80 | extrn RR_Trap_Init:near ; (RRTrap.asm) | ||
| 81 | extrn OEM_Trap_Init:near ; (OEMTrap.asm) | ||
| 82 | |||
| 83 | _TEXT ENDS | ||
| 84 | |||
| 85 | STACK segment | ||
| 86 | extrn kstack_top:byte | ||
| 87 | STACK ends | ||
| 88 | |||
| 89 | ifndef NOHIMEM | ||
| 90 | |||
| 91 | R_CODE segment | ||
| 92 | extrn InitLock:far | ||
| 93 | R_CODE ends | ||
| 94 | |||
| 95 | endif | ||
| 96 | |||
| 97 | page | ||
| 98 | ;****************************************************************************** | ||
| 99 | ; S E G M E N T D E F I N I T I O N S | ||
| 100 | ;****************************************************************************** | ||
| 101 | |||
| 102 | ;****************************************************************************** | ||
| 103 | ; _TEXT segment | ||
| 104 | ;****************************************************************************** | ||
| 105 | |||
| 106 | _TEXT SEGMENT | ||
| 107 | assume cs:_TEXT, ds:DGROUP, es:DGROUP | ||
| 108 | |||
| 109 | ;****************************************************************************** | ||
| 110 | ; FarGoVirtual - far link for GoVirtual | ||
| 111 | ; | ||
| 112 | ; NOTE: this is a FAR routine. | ||
| 113 | ; | ||
| 114 | ; ENTRY: Real Mode | ||
| 115 | ; DS = DGROUP | ||
| 116 | ; | ||
| 117 | ; EXIT: Virtual Mode | ||
| 118 | ; VDM state variables initialized | ||
| 119 | ; | ||
| 120 | ; USED: none | ||
| 121 | ; | ||
| 122 | ;****************************************************************************** | ||
| 123 | FarGoVirtual proc far | ||
| 124 | call GoVirtual | ||
| 125 | ret | ||
| 126 | FarGoVirtual endp | ||
| 127 | |||
| 128 | ;****************************************************************************** | ||
| 129 | ; GoVirtual - go to virtual mode | ||
| 130 | ; | ||
| 131 | ; ENTRY: Real Mode | ||
| 132 | ; DS = DGROUP | ||
| 133 | ; | ||
| 134 | ; EXIT: Virtual Mode | ||
| 135 | ; VDM state variables initialized | ||
| 136 | ; | ||
| 137 | ; USED: none | ||
| 138 | ; | ||
| 139 | ;****************************************************************************** | ||
| 140 | GoVirtual proc near | ||
| 141 | ; | ||
| 142 | PUSH_EAX | ||
| 143 | push bx | ||
| 144 | push bp | ||
| 145 | push ds | ||
| 146 | push es | ||
| 147 | PUSH_FS | ||
| 148 | PUSH_GS | ||
| 149 | ; | ||
| 150 | cli ; interrupts OFF | ||
| 151 | ; | ||
| 152 | ; init VDM state variables | ||
| 153 | ; | ||
| 154 | push es | ||
| 155 | mov ax,[TSS_Seg] | ||
| 156 | mov es,ax ; ES -> TSS | ||
| 157 | call A20_Trap_Init ; init a20 line watch | ||
| 158 | call RR_Trap_Init ; init return to real watch | ||
| 159 | call OEM_Trap_Init ; init any other I/O port watches | ||
| 160 | pop es | ||
| 161 | |||
| 162 | mov [Active_Status],1 | ||
| 163 | |||
| 164 | call InitDMA ; init DMA watcher | ||
| 165 | |||
| 166 | ifndef NOHIMEM | ||
| 167 | call FAR PTR InitLOCK ; init status of TABLE lock | ||
| 168 | endif | ||
| 169 | |||
| 170 | ; | ||
| 171 | ; mask off master 8259 to prevent all interrupts during setup | ||
| 172 | ; | ||
| 173 | call MaskIntAll ; Mask all interrupts | ||
| 174 | ; | ||
| 175 | ; Set the CPU into 386 protected mode. | ||
| 176 | ; | ||
| 177 | ; The following CPU registers are changed to have values | ||
| 178 | ; appropriate to protected mode operation: | ||
| 179 | ; | ||
| 180 | ; CS, DS, ES, SS, TR, LDT, Flags, MSW, GDT, IDT | ||
| 181 | call EnableA20 ; enable A20 address line | ||
| 182 | |||
| 183 | ; | ||
| 184 | ; load CR3 register for paging | ||
| 185 | ; | ||
| 186 | OP32 | ||
| 187 | mov ax,[Page_Dir] ; EAX = 32-bit address of Page Dir | ||
| 188 | |||
| 189 | MOV_CR3_EAX | ||
| 190 | |||
| 191 | ; | ||
| 192 | ; load gdt and ldt base registers | ||
| 193 | ; | ||
| 194 | mov ax,[GDT_Seg] | ||
| 195 | mov ds, ax ; DS:0 = ptr to gdt | ||
| 196 | lgdt qword ptr ds:[GDTD_GSEL] | ||
| 197 | lidt qword ptr ds:[IDTD_GSEL] | ||
| 198 | ; | ||
| 199 | ; go protected and enable paging - turn on bits in CR0 | ||
| 200 | ; | ||
| 201 | MOV_EAX_CR0 | ||
| 202 | |||
| 203 | OP32 | ||
| 204 | or ax,MSW_PROTECT ; or EAX,imm32 - enable PE bit - PROT MODE | ||
| 205 | dw 8000h ; - enable PG bit - PAGING | ||
| 206 | |||
| 207 | MOV_CR0_EAX | ||
| 208 | |||
| 209 | ; far jump to flush prefetch, and reload CS | ||
| 210 | |||
| 211 | db 0eah ; far jmp opcode | ||
| 212 | dw offset _TEXT:pm1 ; offset | ||
| 213 | dw VDMC_GSEL ; selector | ||
| 214 | pm1: | ||
| 215 | ; | ||
| 216 | ; We are now protected, set the Task Register and LDT Register | ||
| 217 | ; | ||
| 218 | mov ax,TSS_GSEL | ||
| 219 | ltr ax | ||
| 220 | |||
| 221 | xor ax, ax ; LDT is null, not needed | ||
| 222 | lldt ax | ||
| 223 | ; | ||
| 224 | ; save current stack pointer for after return to VM | ||
| 225 | ; | ||
| 226 | mov bx,ss ; BX = saved SS | ||
| 227 | mov bp,sp ; BP = saved SP | ||
| 228 | ; | ||
| 229 | ; set the stack selector to RING 0 stack | ||
| 230 | ; | ||
| 231 | mov ax, VDMS_GSEL | ||
| 232 | mov ss, ax | ||
| 233 | mov sp, offset STACK:kstack_top | ||
| 234 | ; | ||
| 235 | ; now reload DS and ES to be data selectors for protected mode | ||
| 236 | ; | ||
| 237 | mov ax, VDMD_GSEL | ||
| 238 | mov ds, ax | ||
| 239 | assume ds:DGROUP | ||
| 240 | mov es, ax | ||
| 241 | assume es:DGROUP | ||
| 242 | |||
| 243 | ; | ||
| 244 | ; reset NT bit so IRET won't attempt a task switch | ||
| 245 | ; | ||
| 246 | pushf | ||
| 247 | pop ax | ||
| 248 | and ax,0FFFh | ||
| 249 | push ax | ||
| 250 | popf | ||
| 251 | ; | ||
| 252 | ; build stack frame for IRET into virtual mode | ||
| 253 | ; | ||
| 254 | push 0 | ||
| 255 | push 0 ; GS | ||
| 256 | push 0 | ||
| 257 | push 0 ; FS | ||
| 258 | push 0 | ||
| 259 | push seg DGROUP ; DS (DGROUP for variable access) | ||
| 260 | push 0 | ||
| 261 | push 0 ; ES | ||
| 262 | |||
| 263 | push 0 | ||
| 264 | push bx ;* virtual mode SS | ||
| 265 | |||
| 266 | push 0 | ||
| 267 | push bp ;* virtual mode ESP | ||
| 268 | |||
| 269 | push 2 ; EFlags high, VM bit set | ||
| 270 | push 3000h ;* EFlags low, NT = 0, IOPL=3, CLI | ||
| 271 | |||
| 272 | push 0 | ||
| 273 | mov ax, [TEXT_Seg] | ||
| 274 | push ax ; CS | ||
| 275 | push 0 | ||
| 276 | mov ax, offset _TEXT:VM_return | ||
| 277 | push ax ; IP | ||
| 278 | |||
| 279 | OP32 ; 32 bit operand size override | ||
| 280 | iret | ||
| 281 | |||
| 282 | ; | ||
| 283 | ; Enter Virtual Mode here | ||
| 284 | ; | ||
| 285 | VM_return: | ||
| 286 | ; | ||
| 287 | ; re-enable interrupts | ||
| 288 | ; | ||
| 289 | call RestIntMask ; Restore interrupt mask | ||
| 290 | POP_GS | ||
| 291 | POP_FS | ||
| 292 | pop es | ||
| 293 | pop ds | ||
| 294 | pop bp | ||
| 295 | pop bx | ||
| 296 | POP_EAX | ||
| 297 | ret | ||
| 298 | GoVirtual endp | ||
| 299 | |||
| 300 | |||
| 301 | ;** SelToSeg - convert selector to a segment number | ||
| 302 | ; | ||
| 303 | ; The protected mode selector value is converted to a | ||
| 304 | ; real mode segment number. | ||
| 305 | ; | ||
| 306 | ; ENTRY BX = selector | ||
| 307 | ; EXIT AX = segment number | ||
| 308 | ; USES BX, Flags, other regs preserved | ||
| 309 | ; | ||
| 310 | ; WARNING This code only works on a 286. It can be | ||
| 311 | ; called only in protected mode. | ||
| 312 | |||
| 313 | SelToSeg proc near | ||
| 314 | push ds | ||
| 315 | mov ax,LDTD_GSEL | ||
| 316 | test bx,TAB_LDT ; is the selector in the LDT? | ||
| 317 | jnz sts_addr ; yes, | ||
| 318 | mov ax,GDTD_GSEL ; selector is in the GDT | ||
| 319 | sts_addr: | ||
| 320 | mov ds,ax | ||
| 321 | and bl,0F8h | ||
| 322 | |||
| 323 | mov ax,word ptr ds:[bx + 2] ; low 16 bits of base address | ||
| 324 | mov bh,ds:[bx + 4] ; high 8 bits of base address | ||
| 325 | shr ax,4 | ||
| 326 | shl bh,4 | ||
| 327 | mov bl,0 | ||
| 328 | add ax,bx ; AX = segment number for selector | ||
| 329 | pop ds | ||
| 330 | ret | ||
| 331 | SelToSeg endp | ||
| 332 | |||
| 333 | _TEXT ends | ||
| 334 | |||
| 335 | end | ||
diff --git a/v4.0/src/MEMM/MEMM/VDMINIT.ASM b/v4.0/src/MEMM/MEMM/VDMINIT.ASM new file mode 100644 index 0000000..a6e7072 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VDMINIT.ASM | |||
| @@ -0,0 +1,527 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VDM_Init - VDM initialization module | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VDM_Init - VDM initialization routine | ||
| 13 | ; | ||
| 14 | ; Version: 0.05 | ||
| 15 | ; | ||
| 16 | ; Date: June 3,1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 06/03/86 Original from VDM MAIN.ASM module | ||
| 27 | ; 06/16/86 0.01 Added code to dword align LL buffer | ||
| 28 | ; 06/21/86 0.02 moved cld in init_pages | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 07/06/86 0.04 changed assume to DGROUP and moved stack out of | ||
| 31 | ; DGROUP | ||
| 32 | ; 07/10/86 0.05 Init of RCODEA_GSEL | ||
| 33 | ; 07/10/86 0.05 Added PageT_Seg | ||
| 34 | ; 07/20/88 Removed debugger codes (pc) | ||
| 35 | ; | ||
| 36 | ;****************************************************************************** | ||
| 37 | ; | ||
| 38 | ; Functional Description: | ||
| 39 | ; | ||
| 40 | ; This module is the general initialization module for the Virtual DOS | ||
| 41 | ; Monitor part of MEMM. This module initializes the protected mode | ||
| 42 | ; GDT, IDT, TSS (and I/O BitMap), and the Page Tables. This module also | ||
| 43 | ; initializes all variables used by the VDM code. This module returns | ||
| 44 | ; to the calling routine in Virtual Mode. | ||
| 45 | ; | ||
| 46 | ;****************************************************************************** | ||
| 47 | .lfcond ; list false conditionals | ||
| 48 | .386p | ||
| 49 | ;****************************************************************************** | ||
| 50 | ; P U B L I C S | ||
| 51 | ;****************************************************************************** | ||
| 52 | |||
| 53 | public VDM_Init | ||
| 54 | public PageD_Seg | ||
| 55 | public PageT_Seg | ||
| 56 | public Page_Dir | ||
| 57 | |||
| 58 | ;****************************************************************************** | ||
| 59 | ; D E F I N E S | ||
| 60 | ;****************************************************************************** | ||
| 61 | include VDMseg.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | include desc.inc | ||
| 64 | include instr386.inc | ||
| 65 | include page.inc | ||
| 66 | |||
| 67 | FALSE equ 0 | ||
| 68 | TRUE equ not FALSE | ||
| 69 | CR equ 0dh | ||
| 70 | LF equ 0ah | ||
| 71 | |||
| 72 | ;****************************************************************************** | ||
| 73 | ; E X T E R N A L R E F E R E N C E S | ||
| 74 | ;****************************************************************************** | ||
| 75 | _DATA SEGMENT | ||
| 76 | extrn P_TABLE_CNT:abs | ||
| 77 | extrn ELOff:word ; offset of LL buffer | ||
| 78 | _DATA ENDS | ||
| 79 | |||
| 80 | _TEXT SEGMENT | ||
| 81 | |||
| 82 | extrn InitBitMap:far ; (vminit.asm) | ||
| 83 | |||
| 84 | _TEXT ENDS | ||
| 85 | |||
| 86 | GDT SEGMENT | ||
| 87 | extrn GDTLEN:abs | ||
| 88 | GDT ENDS | ||
| 89 | |||
| 90 | IDT SEGMENT | ||
| 91 | extrn IDTLEN:abs | ||
| 92 | IDT ENDS | ||
| 93 | |||
| 94 | TSS SEGMENT | ||
| 95 | extrn TSSLEN:abs | ||
| 96 | TSS ENDS | ||
| 97 | |||
| 98 | PAGESEG SEGMENT | ||
| 99 | extrn Page_Area:byte | ||
| 100 | PAGESEG ENDS | ||
| 101 | |||
| 102 | |||
| 103 | LAST SEGMENT | ||
| 104 | extrn SetSegDesc:near | ||
| 105 | extrn SegTo24:near | ||
| 106 | extrn SetPageEntry:near | ||
| 107 | extrn get_init_a20_state:near | ||
| 108 | extrn OEM_Init_Diag_Page:near | ||
| 109 | LAST ENDS | ||
| 110 | |||
| 111 | ;****************************************************************************** | ||
| 112 | ; S E G M E N T D E F I N I T I O N S | ||
| 113 | ;****************************************************************************** | ||
| 114 | |||
| 115 | ; | ||
| 116 | ; Ring 0 stack for VDM exception/int handling | ||
| 117 | ; | ||
| 118 | STACK SEGMENT | ||
| 119 | stkstrt label byte | ||
| 120 | |||
| 121 | db STACK0_SIZE dup(0) | ||
| 122 | |||
| 123 | public kstack_top | ||
| 124 | kstack_top label byte | ||
| 125 | |||
| 126 | db 400h dup (0) | ||
| 127 | public exe_stack | ||
| 128 | exe_stack label byte | ||
| 129 | |||
| 130 | STACK ENDS | ||
| 131 | |||
| 132 | _DATA SEGMENT | ||
| 133 | |||
| 134 | PageD_Seg dw 0 ; segment for Page Directory | ||
| 135 | PageT_Seg dw 0 ; segment for Page Tables | ||
| 136 | Page_Dir dd 0 ; 32 bit address of Page Directory | ||
| 137 | |||
| 138 | _DATA ENDS | ||
| 139 | |||
| 140 | ; | ||
| 141 | ; code | ||
| 142 | ; | ||
| 143 | LAST SEGMENT | ||
| 144 | |||
| 145 | assume cs:LAST, ds:DGROUP, es:DGROUP | ||
| 146 | |||
| 147 | ;****************************************************************************** | ||
| 148 | ; VDM_Init - VDM initialization routine | ||
| 149 | ; | ||
| 150 | ; | ||
| 151 | ; ENTRY: Real Mode | ||
| 152 | ; DS = DGROUP | ||
| 153 | ; GDT = GDT segment | ||
| 154 | ; TSS = TSS segment | ||
| 155 | ; | ||
| 156 | ; EXIT: Real Mode | ||
| 157 | ; VDM Tables initialized | ||
| 158 | ; TSS initialized | ||
| 159 | ; | ||
| 160 | ; USED: none | ||
| 161 | ; | ||
| 162 | ;****************************************************************************** | ||
| 163 | VDM_Init proc near | ||
| 164 | ; | ||
| 165 | pushf | ||
| 166 | pusha | ||
| 167 | PUSH_EAX | ||
| 168 | push ds | ||
| 169 | push es | ||
| 170 | ; | ||
| 171 | push ds | ||
| 172 | pop es ; ES = data | ||
| 173 | ; | ||
| 174 | cli | ||
| 175 | ; | ||
| 176 | call InitGdt ;;; initialize GDT descriptors | ||
| 177 | ; | ||
| 178 | ; initialize Page Table, I/O Bit Map and LIM h/w emulator | ||
| 179 | ; | ||
| 180 | call InitPages ;;; initialize paging tables | ||
| 181 | call InitBitMap ;;; initialize I/O Bit Map | ||
| 182 | ; | ||
| 183 | ; initialize TSS,GDTR,IDTR | ||
| 184 | ; | ||
| 185 | ; set ring 0 SS:SP in the TSS so we can take outer ring traps | ||
| 186 | |||
| 187 | mov ax, seg TSS | ||
| 188 | mov es,ax ; ES -> TSS | ||
| 189 | xor di,di ; ES:DI -> TSS | ||
| 190 | |||
| 191 | mov ES:[di.TSS386_SS0], VDMS_GSEL | ||
| 192 | mov word ptr ES:[di.TSS386_ESP0lo], offset STACK:kstack_top | ||
| 193 | mov word ptr ES:[di.TSS386_ESP0hi], 0 | ||
| 194 | |||
| 195 | ; now set CR3 in the TSS | ||
| 196 | |||
| 197 | db 66h | ||
| 198 | mov ax,word ptr [Page_Dir] ; EAX = page dir 32 bit addr | ||
| 199 | db 66h | ||
| 200 | mov word ptr ES:[di.TSS386_CR3],ax ; mov EAX into CR3 spot in TSS | ||
| 201 | |||
| 202 | ; clear the TSS busy flag | ||
| 203 | |||
| 204 | mov ax,seg GDT | ||
| 205 | mov es, ax ; DS:0 = ptr to gdt | ||
| 206 | |||
| 207 | and byte ptr ES:[TSS_GSEL + 5], 11111101B | ||
| 208 | |||
| 209 | ; | ||
| 210 | ; dword align the LL buffer (move foward) | ||
| 211 | ; | ||
| 212 | mov ax,[ELOff] | ||
| 213 | and ax,0003h ; MOD 4 | ||
| 214 | mov bx,4 | ||
| 215 | sub bx,ax ; BX = amount to add to dword align | ||
| 216 | add [ELOff],bx ; dword align it... | ||
| 217 | |||
| 218 | ; | ||
| 219 | ; and return | ||
| 220 | ; | ||
| 221 | pop es | ||
| 222 | pop ds | ||
| 223 | POP_EAX | ||
| 224 | popa | ||
| 225 | popf | ||
| 226 | ret | ||
| 227 | VDM_Init endp | ||
| 228 | |||
| 229 | ;** InitGdt - initialise GDT | ||
| 230 | ; | ||
| 231 | ; Some of the GDT is statically initialised. This routine | ||
| 232 | ; initialises the rest, except the LDT pointer which | ||
| 233 | ; changes dynamically, and the VDM stack which changes too. | ||
| 234 | ; | ||
| 235 | ; ENTRY GDT:0 = GDT to use. | ||
| 236 | ; EXIT None | ||
| 237 | ; USES All except BP | ||
| 238 | ; | ||
| 239 | ; WARNING This code only works on a 286. | ||
| 240 | ; Designed to be called from real mode ONLY. | ||
| 241 | |||
| 242 | public InitGdt | ||
| 243 | InitGdt proc near | ||
| 244 | push es | ||
| 245 | |||
| 246 | mov ax,GDT | ||
| 247 | mov es,ax ; ES:0 -> gdt | ||
| 248 | |||
| 249 | mov ax,GDT | ||
| 250 | call SegTo24 | ||
| 251 | mov cx,GDTLEN | ||
| 252 | mov ah,D_DATA0 | ||
| 253 | mov bx,GDTD_GSEL | ||
| 254 | call SetSegDesc ; Set up GDT alias descriptor | ||
| 255 | |||
| 256 | mov ax,IDT | ||
| 257 | call SegTo24 | ||
| 258 | mov cx,IDTLEN | ||
| 259 | mov ah,D_DATA0 | ||
| 260 | mov bx,IDTD_GSEL | ||
| 261 | call SetSegDesc ; Set up IDT alias descriptor | ||
| 262 | |||
| 263 | mov ax,TSS | ||
| 264 | call SegTo24 | ||
| 265 | mov cx,TSSLEN | ||
| 266 | mov ah,D_386TSS0 | ||
| 267 | mov bx,TSS_GSEL | ||
| 268 | call SetSegDesc ; Set up TSS descriptor | ||
| 269 | |||
| 270 | mov ah,D_DATA0 | ||
| 271 | mov bx,TSSD_GSEL | ||
| 272 | call SetSegDesc ; Set up TSS alias descriptor | ||
| 273 | |||
| 274 | mov ax,seg _TEXT | ||
| 275 | call SegTo24 | ||
| 276 | mov cx,0 ; 0 = 64K size | ||
| 277 | mov ah,D_CODE0 | ||
| 278 | mov bx,VDMC_GSEL | ||
| 279 | call SetSegDesc ; Set up VDM Code descriptor | ||
| 280 | |||
| 281 | mov ax,_TEXT | ||
| 282 | call SegTo24 | ||
| 283 | mov cx,0 ; 0 = 64K size | ||
| 284 | mov ah,D_DATA0 | ||
| 285 | mov bx,VDMCA_GSEL | ||
| 286 | call SetSegDesc ; Set up VDM Code segment alias descr | ||
| 287 | |||
| 288 | mov ax,R_CODE | ||
| 289 | call SegTo24 | ||
| 290 | mov cx,0 ; 0 = 64K size | ||
| 291 | mov ah,D_DATA0 | ||
| 292 | mov bx,RCODEA_GSEL | ||
| 293 | call SetSegDesc ; Set up R_CODE segment alias descriptor | ||
| 294 | |||
| 295 | mov ax,seg DGROUP | ||
| 296 | call SegTo24 | ||
| 297 | mov cx,0 ; 0 = 64K size | ||
| 298 | mov ah,D_DATA0 | ||
| 299 | mov bx,VDMD_GSEL | ||
| 300 | call SetSegDesc ; Set up VDM Data descriptor | ||
| 301 | |||
| 302 | mov ax, seg STACK ; set up Ring 0 stack | ||
| 303 | call SegTo24 | ||
| 304 | mov cx, offset STACK:kstack_top | ||
| 305 | mov ah, D_DATA0 | ||
| 306 | mov bx, VDMS_GSEL | ||
| 307 | call SetSegDesc | ||
| 308 | |||
| 309 | pop es | ||
| 310 | ret | ||
| 311 | InitGdt endp | ||
| 312 | |||
| 313 | ;** InitPages - initialize Page Directory and Table | ||
| 314 | ; | ||
| 315 | ; This routine initializes a page directory and a page table. | ||
| 316 | ; Both of these are aligned on a physical page boundary by | ||
| 317 | ; starting them at the nearest bndry. Thus, the page table area | ||
| 318 | ; must be large enough to allow this alignment. | ||
| 319 | ; | ||
| 320 | ; The page dir and table set up by this routine maps the linear | ||
| 321 | ; addresses for Virtual mode programs into physical addresses using | ||
| 322 | ; the following scheme. | ||
| 323 | ; Linear Addr Physical Addr | ||
| 324 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 325 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 326 | ; 00110000h - 0100FFFFh 00100000h - 00FFFFFFh (top 15Meg of phys) | ||
| 327 | ; | ||
| 328 | ; ISP,PC: The above was totally unnecessary. When the A20 is turned | ||
| 329 | ; off the 64k at 1M is anyway unaccessible. A better mapping | ||
| 330 | ; has been implemented here: | ||
| 331 | ; | ||
| 332 | ; Linear Addr Physical Addr | ||
| 333 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 334 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 335 | ; 00110000h - 01000000h 00110000h - 01000000h (top 15Meg of phys) | ||
| 336 | ; 01000000h - 0100ffffh xxxx0000h - xxxxffffh (Done in OEMPROC) | ||
| 337 | ; | ||
| 338 | ; | ||
| 339 | ; ENTRY PAGESEG:Page_Area = pointer to page table area. | ||
| 340 | ; DS = DGROUP | ||
| 341 | ; EXIT DS:PageD_Seg = seg ptr for page directory. | ||
| 342 | ; DS:PageT_Seg = seg ptr for page tables | ||
| 343 | ; DS:Page_Dir = 32 bit addr for page directory. | ||
| 344 | ; USES none | ||
| 345 | ; | ||
| 346 | ; WARNING This code only works on a 286/386. | ||
| 347 | ; Designed to be called from real mode ONLY. | ||
| 348 | |||
| 349 | public InitPages | ||
| 350 | InitPages proc near | ||
| 351 | push ax | ||
| 352 | push bx | ||
| 353 | push cx | ||
| 354 | push dx | ||
| 355 | push di | ||
| 356 | push es | ||
| 357 | cld ; strings foward | ||
| 358 | ; | ||
| 359 | ; get physical pointer to nearest page | ||
| 360 | ; | ||
| 361 | mov ax,offset PAGESEG:Page_Area | ||
| 362 | add ax,15 | ||
| 363 | shr ax,4 ; AX = seg offset for page area | ||
| 364 | mov bx,PAGESEG ; PAGESEG is on a 256 boundary | ||
| 365 | add ax,bx ; AX = seg offset for page area | ||
| 366 | add ax,0FFh ; 0FFh = # of paras in page - 1 | ||
| 367 | xor al,al ; AX = seg addr for page align | ||
| 368 | mov [PageD_Seg],ax ; save it | ||
| 369 | ; | ||
| 370 | xor di,di | ||
| 371 | mov es,ax ; ES:DI = ptr to Page Directory | ||
| 372 | ; | ||
| 373 | mov dl,ah | ||
| 374 | shr dl,4 ; DL = bits 16 - 19 | ||
| 375 | xor dh,dh ; DX = bits 16 - 31 | ||
| 376 | shl ah,4 ; AX = bits 0 - 15 | ||
| 377 | mov word ptr [Page_Dir],AX ; DX,AX = 32 bit addr of Page Directory | ||
| 378 | mov word ptr [Page_Dir+2],DX ; save it | ||
| 379 | ; | ||
| 380 | ; get addr of Page Table for Page Directory entry | ||
| 381 | ; | ||
| 382 | add ax,1000h ; add page | ||
| 383 | adc dx,0h ; carry it => DX,AX = addr of page table | ||
| 384 | ; | ||
| 385 | ; set entries in page directory | ||
| 386 | ; | ||
| 387 | ; ES:[DI] pts to first entry in page directory | ||
| 388 | ; DX,AX = addr of first page table | ||
| 389 | ; | ||
| 390 | mov bh,0 | ||
| 391 | mov bl,P_AVAIL ; make table available to all | ||
| 392 | mov cx,P_TABLE_CNT ; set entries in page table directory | ||
| 393 | ; for existing page tables. | ||
| 394 | init_dir: | ||
| 395 | call SetPageEntry ; set entry for first page table | ||
| 396 | ; | ||
| 397 | ; ES:[DI] pts to next entry in page directory | ||
| 398 | add ax,1000h | ||
| 399 | adc dx,0 ; DX,AX = addr of next page table | ||
| 400 | loop init_dir ; set next entry in dir | ||
| 401 | ; | ||
| 402 | ; set rest of entries in page directory to not present | ||
| 403 | mov bh,0 | ||
| 404 | mov bl,NOT P_PRES ; mark page table as not present | ||
| 405 | mov cx,400h | ||
| 406 | sub cx,P_TABLE_CNT ; set rest of entries in directory | ||
| 407 | set_dir: | ||
| 408 | call SetPageEntry | ||
| 409 | loop set_dir | ||
| 410 | ; | ||
| 411 | ; set entries in page tables | ||
| 412 | ; | ||
| 413 | ; first 1 Meg | ||
| 414 | ; Linear Addr Physical Addr | ||
| 415 | ; 00000000h - 000FFFFFh 00000000h - 000FFFFFh | ||
| 416 | ; | ||
| 417 | mov ax,[PageD_Seg] ; get segment for page directory | ||
| 418 | add ax,0100h ; add 1 page to get to first page table | ||
| 419 | mov [PageT_Seg],ax ; save it | ||
| 420 | |||
| 421 | mov es,ax | ||
| 422 | xor di,di ; ES:[DI] pts to first page table | ||
| 423 | |||
| 424 | xor dx,dx | ||
| 425 | xor ax,ax ; start with physical addr = 00000000h | ||
| 426 | mov bh,0 | ||
| 427 | mov bl,P_AVAIL ; make pages available to all | ||
| 428 | mov cx,100h ; set 1 Meg worth of entries in table | ||
| 429 | set1_tentry: | ||
| 430 | call SetPageEntry | ||
| 431 | ; ES:[DI] pts to next page table entry | ||
| 432 | add ax,1000h ; next physical page | ||
| 433 | adc dx,0h ; address in DX,AX | ||
| 434 | loop set1_tentry ;Q: done with this page table | ||
| 435 | ; N: the loop again | ||
| 436 | ; Y: set next entries in next tables | ||
| 437 | ; 64k wraparound at 1.0 Meg | ||
| 438 | ; Linear Addr Physical Addr | ||
| 439 | ; 00100000h - 0010FFFFh 00000000h - 0000FFFFh (64k wraparound) | ||
| 440 | ; | ||
| 441 | call get_init_a20_state ; the physical a20 state has already | ||
| 442 | ; been established | ||
| 443 | jnz skip_wrap | ||
| 444 | xor dx,dx | ||
| 445 | xor ax,ax ; start with physical addr = 00000000h | ||
| 446 | skip_wrap: | ||
| 447 | mov bh,0 | ||
| 448 | mov bl,P_AVAIL ; make pages available to all | ||
| 449 | mov cx,10h ; set 64k worth of entries | ||
| 450 | set2_tentry: | ||
| 451 | call SetPageEntry | ||
| 452 | ; ES:[DI] pts to next page table entry | ||
| 453 | add ax,1000h ; next physical page | ||
| 454 | adc dx,0h ; address in DX,AX | ||
| 455 | loop set2_tentry ;Q: done with the wraparound entries | ||
| 456 | ; N: loop again | ||
| 457 | ; Y: all done | ||
| 458 | ; | ||
| 459 | ; last (15M - 64K) of linear addresses ( for Move Block/Loadall ) | ||
| 460 | ; Linear Addr Physical Addr | ||
| 461 | ; 00110000h - 01000000h 00110000h - 01000000h | ||
| 462 | ; | ||
| 463 | mov dx,0011h | ||
| 464 | xor ax,ax ; start with 00110000h physical | ||
| 465 | mov bh,0 | ||
| 466 | mov bl,P_AVAIL ; make pages available to all | ||
| 467 | mov cx,(4*400h)-100h-10h ; (15M-64K) worth of Page Table Entries | ||
| 468 | set3_tentry: | ||
| 469 | call SetPageEntry | ||
| 470 | ; ES:[DI] pts to next page table entry | ||
| 471 | add ax,1000h ; next physical page | ||
| 472 | adc dx,0h ; address in DX,AX | ||
| 473 | loop set3_tentry ;Q: done with last entries | ||
| 474 | ; N: loop again | ||
| 475 | ; Y: all done | ||
| 476 | |||
| 477 | ; | ||
| 478 | ; fill out entries in last table as not present | ||
| 479 | ; | ||
| 480 | xor ax,ax | ||
| 481 | xor dx,dx ; addr = 0 | ||
| 482 | mov bh,0 | ||
| 483 | mov bl,0 ; page not present | ||
| 484 | ; | ||
| 485 | ; we can actually forget about this last page table because we | ||
| 486 | ; are not going to use them | ||
| 487 | ; | ||
| 488 | mov cx,400h ; last table | ||
| 489 | setL_tentry: | ||
| 490 | call SetPageEntry ; set this entry | ||
| 491 | loop setL_tentry | ||
| 492 | ; | ||
| 493 | ; our honorable OEM Compaq has to be supported, so we have this hook into | ||
| 494 | ; OEMPROC to modify the last page table to point at the diagnostics segment | ||
| 495 | ; | ||
| 496 | call OEM_Init_Diag_Page | ||
| 497 | ; | ||
| 498 | ; all done with page dir and table setup | ||
| 499 | ; set up page directory and page table selectors | ||
| 500 | ; | ||
| 501 | mov ax,seg GDT | ||
| 502 | mov es,ax ; ES pts to GDT | ||
| 503 | |||
| 504 | mov ax,[PageT_Seg] ; seg for page tables | ||
| 505 | call SegTo24 | ||
| 506 | mov cx,0 ; enough room for tables | ||
| 507 | mov ah,D_DATA0 | ||
| 508 | mov bx,PAGET_GSEL | ||
| 509 | call SetSegDesc ; set up page tables entry | ||
| 510 | |||
| 511 | ; | ||
| 512 | ; EXIT | ||
| 513 | ; | ||
| 514 | pop es | ||
| 515 | pop di | ||
| 516 | pop dx | ||
| 517 | pop cx | ||
| 518 | pop bx | ||
| 519 | pop ax | ||
| 520 | ret | ||
| 521 | InitPages endp | ||
| 522 | |||
| 523 | LAST ends | ||
| 524 | |||
| 525 | END | ||
| 526 | |||
| 527 | |||
diff --git a/v4.0/src/MEMM/MEMM/VDMSEG.INC b/v4.0/src/MEMM/MEMM/VDMSEG.INC new file mode 100644 index 0000000..5a73bb3 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VDMSEG.INC | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: VDMSEG.INC - Segment Ordering and attributes for VDM | ||
| 10 | ; | ||
| 11 | ; Version: 0.04 | ||
| 12 | ; | ||
| 13 | ; Date: May 12, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/03/86 C changed order and added STACK and STACK0,STACK0_SIZE | ||
| 26 | ; 06/06/86 C changed CODE to _TEXT and DATA to _DATA | ||
| 27 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 28 | ; 07/05/86 0.04 Re-organized to allow code seg move | ||
| 29 | ; 06/03/88 add use16 to all segments | ||
| 30 | ; | ||
| 31 | ;****************************************************************************** | ||
| 32 | ifndef INC_LIST | ||
| 33 | .xlist | ||
| 34 | endif | ||
| 35 | |||
| 36 | ifndef NOHIMEM | ||
| 37 | ; | ||
| 38 | ; SEGMENT definitions and order | ||
| 39 | ; | ||
| 40 | |||
| 41 | ;* CODE area containing EMM/VDISK headers and writeable Real mode code | ||
| 42 | R_CODE SEGMENT PARA USE16 PUBLIC 'R_CODE' | ||
| 43 | R_CODE ENDS | ||
| 44 | |||
| 45 | ;* Contains initialized variables and variables used at startup. | ||
| 46 | _DATA SEGMENT WORD USE16 PUBLIC 'DATA' | ||
| 47 | _DATA ENDS | ||
| 48 | |||
| 49 | ;* read only constants for C | ||
| 50 | CONST SEGMENT WORD USE16 PUBLIC 'CONST' | ||
| 51 | CONST ENDS | ||
| 52 | |||
| 53 | ;* uninitialized static data for C | ||
| 54 | _BSS SEGMENT WORD USE16 PUBLIC 'BSS' | ||
| 55 | _BSS ENDS | ||
| 56 | |||
| 57 | ;* Ring 0 stack in VDM | ||
| 58 | STACK SEGMENT PARA USE16 STACK 'STACK' | ||
| 59 | STACK ENDS | ||
| 60 | |||
| 61 | ; | ||
| 62 | ; data group | ||
| 63 | ; | ||
| 64 | DGROUP GROUP _DATA,CONST,_BSS | ||
| 65 | |||
| 66 | ;* The code comprising the system. Must be READ-ONLY in real mode. | ||
| 67 | _TEXT SEGMENT BYTE USE16 PUBLIC 'CODE' | ||
| 68 | _TEXT ENDS | ||
| 69 | |||
| 70 | ;* Global Descriptor Table | ||
| 71 | GDT SEGMENT PARA USE16 COMMON | ||
| 72 | GDT ENDS | ||
| 73 | |||
| 74 | ;* Local Descriptor Table | ||
| 75 | LDT SEGMENT PARA USE16 COMMON | ||
| 76 | LDT ENDS | ||
| 77 | |||
| 78 | ;* Interrupt Descriptor Table | ||
| 79 | IDT SEGMENT PARA USE16 COMMON | ||
| 80 | IDT ENDS | ||
| 81 | |||
| 82 | ;* Task State Segment | ||
| 83 | TSS SEGMENT PARA USE16 COMMON | ||
| 84 | TSS ENDS | ||
| 85 | |||
| 86 | ;* Contains initialized variables and variables used at startup. | ||
| 87 | PAGESEG SEGMENT PARA USE16 PUBLIC 'PAGES' | ||
| 88 | PAGESEG ENDS | ||
| 89 | |||
| 90 | ;* Initialization code and variables. Used for data later. | ||
| 91 | ; Must be last segment. | ||
| 92 | LAST SEGMENT PARA USE16 PUBLIC 'LAST' | ||
| 93 | LAST ENDS | ||
| 94 | |||
| 95 | |||
| 96 | |||
| 97 | else | ||
| 98 | ; | ||
| 99 | ; SEGMENT definitions and order | ||
| 100 | ; | ||
| 101 | |||
| 102 | ;* CODE area containing EMM/VDISK headers and writeable Real mode code | ||
| 103 | R_CODE SEGMENT PARA USE16 PUBLIC 'R_CODE' | ||
| 104 | R_CODE ENDS | ||
| 105 | |||
| 106 | ;* Global Descriptor Table | ||
| 107 | GDT SEGMENT PARA USE16 COMMON | ||
| 108 | GDT ENDS | ||
| 109 | |||
| 110 | ;* Local Descriptor Table | ||
| 111 | LDT SEGMENT PARA USE16 COMMON | ||
| 112 | LDT ENDS | ||
| 113 | |||
| 114 | ;* Interrupt Descriptor Table | ||
| 115 | IDT SEGMENT PARA USE16 COMMON | ||
| 116 | IDT ENDS | ||
| 117 | |||
| 118 | ;* Task State Segment | ||
| 119 | TSS SEGMENT PARA USE16 COMMON | ||
| 120 | TSS ENDS | ||
| 121 | |||
| 122 | ;* Contains initialized variables and variables used at startup. | ||
| 123 | _DATA SEGMENT WORD USE16 PUBLIC 'DATA' | ||
| 124 | _DATA ENDS | ||
| 125 | |||
| 126 | ;* read only constants for C | ||
| 127 | CONST SEGMENT WORD USE16 PUBLIC 'CONST' | ||
| 128 | CONST ENDS | ||
| 129 | |||
| 130 | ;* uninitialized static data for C | ||
| 131 | _BSS SEGMENT WORD USE16 PUBLIC 'BSS' | ||
| 132 | _BSS ENDS | ||
| 133 | |||
| 134 | ;* Ring 0 stack in VDM | ||
| 135 | STACK SEGMENT PARA USE16 STACK 'STACK' | ||
| 136 | STACK ENDS | ||
| 137 | |||
| 138 | ; | ||
| 139 | ; data group | ||
| 140 | ; | ||
| 141 | DGROUP GROUP _DATA,CONST,_BSS | ||
| 142 | |||
| 143 | ;* The code comprising the system. Must be READ-ONLY in real mode. | ||
| 144 | _TEXT SEGMENT BYTE USE16 PUBLIC 'CODE' | ||
| 145 | _TEXT ENDS | ||
| 146 | |||
| 147 | ;* Contains dynamically sized emm data structures. | ||
| 148 | VDATA SEGMENT WORD USE16 PUBLIC 'VDATA' | ||
| 149 | VDATA ENDS | ||
| 150 | |||
| 151 | ;* Contains initialized variables and variables used at startup. | ||
| 152 | PAGESEG SEGMENT PARA USE16 PUBLIC 'PAGES' | ||
| 153 | PAGESEG ENDS | ||
| 154 | |||
| 155 | ;* Initialization code and variables. Used for data later. | ||
| 156 | ; Must be last segment. | ||
| 157 | LAST SEGMENT PARA USE16 PUBLIC 'LAST' | ||
| 158 | LAST ENDS | ||
| 159 | endif | ||
| 160 | ; | ||
| 161 | ; segment related equates | ||
| 162 | ; | ||
| 163 | |||
| 164 | ; ring 0 stack size | ||
| 165 | STACK0_SIZE equ 512 | ||
| 166 | |||
| 167 | .list ; end of VDMSEG.INC | ||
| 168 | |||
diff --git a/v4.0/src/MEMM/MEMM/VDMSEL.INC b/v4.0/src/MEMM/MEMM/VDMSEL.INC new file mode 100644 index 0000000..f408c40 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VDMSEL.INC | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: VDMSEL.INC - Selector Definitions for MEMM | ||
| 10 | ; | ||
| 11 | ; Version: 0.05 | ||
| 12 | ; | ||
| 13 | ; Date: May 12, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/07/86 C merged with module from Rick | ||
| 26 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 27 | ; 07/10/86 0.05 Changed CODE_GSEL to RCODEA_GSEL | ||
| 28 | ; 07/20/88 Remove debugger selectors | ||
| 29 | ; | ||
| 30 | ;****************************************************************************** | ||
| 31 | ifndef INC_LIST | ||
| 32 | .xlist | ||
| 33 | endif | ||
| 34 | |||
| 35 | |||
| 36 | ; | ||
| 37 | ; DESCRIPTION | ||
| 38 | ; | ||
| 39 | ; These are the fixed selector numbers for the GDT and LDT | ||
| 40 | ; | ||
| 41 | ; All are declared with RPL = 0 so they can easily be used | ||
| 42 | ; as table indices. | ||
| 43 | ; | ||
| 44 | ; Do not change anything without consulting files which include | ||
| 45 | ; this one. Add new selectors to the end and update the | ||
| 46 | ; gdt declaration and initialisation code elsewhere. | ||
| 47 | ; | ||
| 48 | |||
| 49 | ; Define LDT and GDT table bits | ||
| 50 | |||
| 51 | TAB_LDT equ 4h | ||
| 52 | TAB_GDT equ 0h | ||
| 53 | |||
| 54 | |||
| 55 | ; Define GDT selectors | ||
| 56 | |||
| 57 | GDTD_GSEL equ 008h OR TAB_GDT ; gdt data alias | ||
| 58 | IDTD_GSEL equ 010h OR TAB_GDT ; idt data alias | ||
| 59 | LDT_GSEL equ 018h OR TAB_GDT ; ldt | ||
| 60 | LDTD_GSEL equ 020h OR TAB_GDT ; ldt data alias | ||
| 61 | TSS_GSEL equ 028h OR TAB_GDT ; tss | ||
| 62 | TSSD_GSEL equ 030h OR TAB_GDT ; tss data alias | ||
| 63 | RM_IDT_GSEL equ 038h OR TAB_GDT ; real mode idt (locn 0) | ||
| 64 | ROMDATA_GSEL equ 040h OR TAB_GDT ; maps 40:0 - DON'T CHANGE!! | ||
| 65 | VDMC_GSEL equ 048h OR TAB_GDT ; VDM Code selector | ||
| 66 | VDMD_GSEL equ 050h OR TAB_GDT ; VDM Data Selector | ||
| 67 | VDMS_GSEL equ 058h OR TAB_GDT ; VDM stack selector | ||
| 68 | MONO_GSEL equ 060h OR TAB_GDT ; monochrome display memory | ||
| 69 | COLOUR_GSEL equ 068h OR TAB_GDT ; colour display memory | ||
| 70 | EGA1_GSEL equ 070h OR TAB_GDT ; first EGA sel | ||
| 71 | EGA2_GSEL equ 078h OR TAB_GDT ; second EGA sel | ||
| 72 | LOADALL_GSEL equ 080h OR TAB_GDT ; loadall buffer - DON'T CHANGE | ||
| 73 | ;DEBC_GSEL equ 088h or TAB_GDT ; debugger work descr | ||
| 74 | ;DEBD_GSEL equ 090h or TAB_GDT ; debugger work descr | ||
| 75 | ;DEBW1_GSEL equ 098h or TAB_GDT ; debugger work descr | ||
| 76 | ;DEBW2_GSEL equ 0A0h or TAB_GDT ; debugger work descr | ||
| 77 | DEB1_GSEL equ 088h or TAB_GDT ; deb386 word descr | ||
| 78 | DEB2_GSEL equ 090h or TAB_GDT ; deb386 word descr | ||
| 79 | DEB3_GSEL equ 098h or TAB_GDT ; deb386 word descr | ||
| 80 | DEB4_GSEL equ 0A0h or TAB_GDT ; deb386 word descr | ||
| 81 | DEB5_GSEL equ 0A8h or TAB_GDT ; deb386 word descr | ||
| 82 | DEBX_GSEL equ 0B0h or TAB_GDT ; deb386 descr for all of addressing space | ||
| 83 | K_PUTC286 equ 0B8h OR TAB_GDT ; 286 call gate to kputc | ||
| 84 | K_GETC286 equ 0C0h OR TAB_GDT ; 286 call gate to kgetc | ||
| 85 | RCODEA_GSEL equ 0C8h OR TAB_GDT ; data alias for R_CODE segment | ||
| 86 | VM1_GSEL equ 0D0h OR TAB_GDT ; scratch for vm handler | ||
| 87 | VM2_GSEL equ 0D8h OR TAB_GDT ; scratch for vm handler | ||
| 88 | MBSRC_GSEL equ 0E0h OR TAB_GDT ; source sel for move blk | ||
| 89 | MBTAR_GSEL equ 0E8h OR TAB_GDT ; target sel for move blk | ||
| 90 | PAGET_GSEL equ 0F0h OR TAB_GDT ; page table area sel | ||
| 91 | VDMCA_GSEL equ 0F8h OR TAB_GDT ; VDM code segment alias | ||
| 92 | EMM1_GSEL equ 100h OR TAB_GDT ; EMM scratch selector | ||
| 93 | EMM2_GSEL equ 108h OR TAB_GDT ; EMM scratch selector | ||
| 94 | OEM0_GSEL equ 110h OR TAB_GDT ; OEM specific selector | ||
| 95 | OEM1_GSEL equ 118h OR TAB_GDT ; OEM specific selector | ||
| 96 | OEM2_GSEL equ 120h OR TAB_GDT ; OEM specific selector | ||
| 97 | OEM3_GSEL equ 128h OR TAB_GDT ; OEM specific selector | ||
| 98 | USER1_GSEL equ 130h OR TAB_GDT ; USER data structure | ||
| 99 | |||
| 100 | .list ; end of VDMSEL.INC | ||
| 101 | \ No newline at end of file | ||
diff --git a/v4.0/src/MEMM/MEMM/VM386.INC b/v4.0/src/MEMM/MEMM/VM386.INC new file mode 100644 index 0000000..19ce94e --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VM386.INC | |||
| @@ -0,0 +1,206 @@ | |||
| 1 | |||
| 2 | |||
| 3 | ;****************************************************************************** | ||
| 4 | ; | ||
| 5 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 6 | ; | ||
| 7 | ; Title: MEMM - MICROSOFT Expanded Memory Manager 386 | ||
| 8 | ; | ||
| 9 | ; Module: VM386.INC | ||
| 10 | ; | ||
| 11 | ; Version: 0.03 | ||
| 12 | ; | ||
| 13 | ; Date: May 12, 1986 | ||
| 14 | ; | ||
| 15 | ; Author: | ||
| 16 | ; | ||
| 17 | ;****************************************************************************** | ||
| 18 | ; | ||
| 19 | ; Change log: | ||
| 20 | ; | ||
| 21 | ; DATE REVISION DESCRIPTION | ||
| 22 | ; -------- -------- ------------------------------------------------------- | ||
| 23 | ; Original | ||
| 24 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 25 | ; 06/08/86 B Added Disable A20 equates | ||
| 26 | ; 06/14/86 C Added MOV_CDTR_FRAME, PROT_INS_FRAME, and changed | ||
| 27 | ; VTFO from 2 to 4 to reflect push of EBP from BP | ||
| 28 | ; 06/15/86 D Added GPFAULT_FRAME | ||
| 29 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 30 | ; 07/01/86 0.03 Added structures for accessing memory | ||
| 31 | ; | ||
| 32 | ;****************************************************************************** | ||
| 33 | ifndef INC_LIST | ||
| 34 | .xlist | ||
| 35 | endif | ||
| 36 | |||
| 37 | ; | ||
| 38 | ; Structures for accessing memory | ||
| 39 | ; | ||
| 40 | WordS struc | ||
| 41 | LowByte db ? | ||
| 42 | HighByte db ? | ||
| 43 | WordS ends | ||
| 44 | |||
| 45 | DwordS struc | ||
| 46 | LowWord dw ? | ||
| 47 | HighWord dw ? | ||
| 48 | DwordS ends | ||
| 49 | |||
| 50 | ; | ||
| 51 | ; Structure for accessing stack frame pushed during trap exit from VM | ||
| 52 | ; | ||
| 53 | |||
| 54 | VM_TRAP_FRAME struc | ||
| 55 | VMTF_EIP dw ? ; EIP (low) | ||
| 56 | dw ? ; EIP (high) | ||
| 57 | VMTF_CS dw ? ; CS | ||
| 58 | dw ? ; (padding) | ||
| 59 | VMTF_EFLAGS dw ? ; EFLAGS (low) | ||
| 60 | VMTF_EFLAGShi dw ? ; EFLAGS (high) | ||
| 61 | VMTF_ESP dw ? ; ESP (low) | ||
| 62 | dw ? ; ESP (high) | ||
| 63 | VMTF_SS dw ? ; SS | ||
| 64 | dw ? ; (padding) | ||
| 65 | VMTF_ES dw ? ; ES | ||
| 66 | dw ? ; (padding) | ||
| 67 | VMTF_DS dw ? ; DS | ||
| 68 | dw ? ; (padding) | ||
| 69 | VMTF_FS dw ? ; FS | ||
| 70 | dw ? ; (padding) | ||
| 71 | VMTF_GS dw ? ; GS | ||
| 72 | dw ? ; (padding) | ||
| 73 | VM_TRAP_FRAME ends | ||
| 74 | ; | ||
| 75 | ; Used in EmMovCDTR (vminst.asm) | ||
| 76 | MOV_CDTR_FRAME struc | ||
| 77 | MCF_WBP dw ? ; Work BP | ||
| 78 | MCF_WES dw ? ; Work ES | ||
| 79 | MCF_EAX dw ? ; EAXlo | ||
| 80 | dw ? ; EAXhi | ||
| 81 | MCF_ESI dw ? ; ESIlo | ||
| 82 | dw ? ; ESIhi | ||
| 83 | MCF_EBX dw ? ; EBXlo | ||
| 84 | dw ? ; EBXhi | ||
| 85 | MCF_EBP dw ? ; EBPlo | ||
| 86 | dw ? ; EBPhi | ||
| 87 | MCF_VMERR dw ? ; VM Error Code (low) | ||
| 88 | dw ? ; VM Error Code (high) | ||
| 89 | MCF_VMEIP dw ? ; VM EIP (low) | ||
| 90 | dw ? ; VM EIP (high) | ||
| 91 | MCF_VMCS dw ? ; VM CS | ||
| 92 | dw ? ; (padding) | ||
| 93 | MCF_VMEFLAGS dw ? ; VM EFLAGS (low) | ||
| 94 | MCF_VMEFLAGShi dw ? ; VM EFLAGS (high) | ||
| 95 | MCF_VMESP dw ? ; VM ESP (low) | ||
| 96 | dw ? ; VM ESP (high) | ||
| 97 | MCF_VMSS dw ? ; VM SS | ||
| 98 | dw ? ; (padding) | ||
| 99 | MCF_VMES dw ? ; VM ES | ||
| 100 | dw ? ; (padding) | ||
| 101 | MCF_VMDS dw ? ; VM DS | ||
| 102 | dw ? ; (padding) | ||
| 103 | MCF_VMFS dw ? ; VM FS | ||
| 104 | dw ? ; (padding) | ||
| 105 | MCF_VMGS dw ? ; VM GS | ||
| 106 | dw ? ; (padding) | ||
| 107 | MOV_CDTR_FRAME ends | ||
| 108 | ; | ||
| 109 | ; Used in EmProtIns (vminst.asm) | ||
| 110 | PROT_INS_FRAME struc | ||
| 111 | PIF_WBP dw ? ; Work BP | ||
| 112 | PIF_WES dw ? ; Work ES | ||
| 113 | PIF_AX dw ? ; EAXlo | ||
| 114 | PIF_DX dw ? ; EDXlo | ||
| 115 | PIF_ESI dw ? ; ESIlo | ||
| 116 | dw ? ; ESIhi | ||
| 117 | PIF_EBX dw ? ; EBXlo | ||
| 118 | dw ? ; EBXhi | ||
| 119 | PIF_EBP dw ? ; EBPlo | ||
| 120 | dw ? ; EBPhi | ||
| 121 | PIF_VMERR dw ? ; VM Error Code (low) | ||
| 122 | dw ? ; VM Error Code (high) | ||
| 123 | PIF_VMEIP dw ? ; VM EIP (low) | ||
| 124 | dw ? ; VM EIP (high) | ||
| 125 | PIF_VMCS dw ? ; VM CS | ||
| 126 | dw ? ; (padding) | ||
| 127 | PIF_VMEFLAGS dw ? ; VM EFLAGS (low) | ||
| 128 | PIF_VMEFLAGShi dw ? ; VM EFLAGS (high) | ||
| 129 | PIF_VMESP dw ? ; VM ESP (low) | ||
| 130 | dw ? ; VM ESP (high) | ||
| 131 | PIF_VMSS dw ? ; VM SS | ||
| 132 | dw ? ; (padding) | ||
| 133 | PIF_VMES dw ? ; VM ES | ||
| 134 | dw ? ; (padding) | ||
| 135 | PIF_VMDS dw ? ; VM DS | ||
| 136 | dw ? ; (padding) | ||
| 137 | PIF_VMFS dw ? ; VM FS | ||
| 138 | dw ? ; (padding) | ||
| 139 | PIF_VMGS dw ? ; VM GS | ||
| 140 | dw ? ; (padding) | ||
| 141 | PROT_INS_FRAME ends | ||
| 142 | ; | ||
| 143 | GPFAULT_FRAME struc | ||
| 144 | GPF_ESI dw ? ; ESIlo | ||
| 145 | dw ? ; ESIhi | ||
| 146 | GPF_EBX dw ? ; EBXlo | ||
| 147 | dw ? ; EBXhi | ||
| 148 | GPF_EBP dw ? ; EBPlo | ||
| 149 | dw ? ; EBPhi | ||
| 150 | GPFAULT_FRAME ends | ||
| 151 | ; | ||
| 152 | ; The following constants define the offset of the Virtual Mode trap stack | ||
| 153 | ; frame (from current SP assuming BP has been pushed) for the two cases: | ||
| 154 | ; 1) exceptions that don't push error codes and 2) those that do. | ||
| 155 | ; | ||
| 156 | VTFO equ 4 ; offset of VM trap stack frame | ||
| 157 | VTFOE equ VTFO + 4 ; as above, but including error code | ||
| 158 | ; | ||
| 159 | ; These constants are used to sanity-check the value of SP when one of | ||
| 160 | ; the exception handlers has been entered: | ||
| 161 | ; | ||
| 162 | STACK segment | ||
| 163 | extrn kstack_top:byte | ||
| 164 | STACK ends | ||
| 165 | |||
| 166 | ; Trap/no error | ||
| 167 | VMT_STACK equ offset STACK:kstack_top - size VM_TRAP_FRAME - VTFO | ||
| 168 | ; Trap w/error | ||
| 169 | VMTERR_STACK equ offset STACK:kstack_top - size VM_TRAP_FRAME - VTFOE | ||
| 170 | |||
| 171 | ;****************************************************************************** | ||
| 172 | ; E R R O R C O D E S | ||
| 173 | ;****************************************************************************** | ||
| 174 | ; | ||
| 175 | PrivErr equ 0000h ; Privileged Operation Error class | ||
| 176 | ErrLGDT equ 0000h ; Client tried to execute a LGDT | ||
| 177 | ErrLIDT equ 0001h ; Client tried to execute a LIDT | ||
| 178 | ErrLMSW equ 0002h ; Client tried to execute a LMSW | ||
| 179 | Err2LL equ 0003h ; Client tried to execute a 286 Loadall | ||
| 180 | Err3LL equ 0004h ; Client tried to execute a 386 Loadall | ||
| 181 | ErrMovCR equ 0005h ; Client tried to execute a CRn mov | ||
| 182 | ErrMovDR equ 0006h ; Client tried to execute a DRn mov | ||
| 183 | ErrMovTR equ 0007h ; Client tried to execute a TRn mov | ||
| 184 | |||
| 185 | ExcpErr equ 0001h ; Exception Error class | ||
| 186 | ErrDIV equ 0000h ; Divide Error | ||
| 187 | ErrINT1 equ 0001h ; Debug Exception | ||
| 188 | ErrNMI equ 0002h ; NMI | ||
| 189 | ErrINT3 equ 0003h ; Int 3 | ||
| 190 | ErrINTO equ 0004h ; Int O error | ||
| 191 | ErrBounds equ 0005h ; Array Bounds Check | ||
| 192 | ErrOpCode equ 0006h ; Invalid Opcode | ||
| 193 | ErrCoPNA equ 0007h ; Coprocessor Device not available | ||
| 194 | ErrDouble equ 0008h ; Double Fault | ||
| 195 | ErrCoPseg equ 0009h ; Coprocessor Segment Overrun | ||
| 196 | ErrTSS equ 000Ah ; Invalid TSS | ||
| 197 | ErrSegNP equ 000Bh ; Segment not Present | ||
| 198 | ErrStack equ 000Ch ; Stack Fault | ||
| 199 | ErrGP equ 000Dh ; General Protection Fault | ||
| 200 | ErrPage equ 000Eh ; Page Fault | ||
| 201 | ErrCoPerr equ 0010h ; Coprocessor Error | ||
| 202 | ErrWrite equ 0020h ; Attempt to write to protected area | ||
| 203 | ErrDMA equ 0021h ; Attempt to DMA into page frame (not for user) | ||
| 204 | ErrINTProt equ 0022h ; General Protected interrupt error | ||
| 205 | |||
| 206 | .list ; end of VM386.INC | ||
diff --git a/v4.0/src/MEMM/MEMM/VMINIT.ASM b/v4.0/src/MEMM/MEMM/VMINIT.ASM new file mode 100644 index 0000000..5b69b1a --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VMINIT.ASM | |||
| @@ -0,0 +1,292 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VMINIT.ASM - Initialization routines for VM-DOS | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VMINIT - Initialization routines for MEMM/ VDM | ||
| 13 | ; | ||
| 14 | ; Version: 0.04 | ||
| 15 | ; | ||
| 16 | ; Date: January 30, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 01/30/86 Original | ||
| 27 | ; 04/07/86 A Added InitBitMap | ||
| 28 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 29 | ; 06/18/86 0.01 Re-arranged comments, etc. | ||
| 30 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 31 | ; 07/03/86 0.03 Added call to Kybd_Watch | ||
| 32 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 33 | ; 07/30/86 0.06 removed PortClear reference | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ; | ||
| 37 | ; Functional Description: | ||
| 38 | ; | ||
| 39 | ; This module contains various initialization routines for Virtual DOS | ||
| 40 | ; | ||
| 41 | ;****************************************************************************** | ||
| 42 | .386p | ||
| 43 | .lfcond ; list false conditionals | ||
| 44 | page | ||
| 45 | ;****************************************************************************** | ||
| 46 | ; P U B L I C D E C L A R A T I O N S | ||
| 47 | ;****************************************************************************** | ||
| 48 | ; | ||
| 49 | public vminit ; module label | ||
| 50 | public InitBitMap ; init I/O Bit Map | ||
| 51 | public PortTrap ; set bit(s) in I/O Bit Map | ||
| 52 | ifdef oldstuff | ||
| 53 | public PortClear ; clear bit(s) in I/O Bit Map | ||
| 54 | endif | ||
| 55 | public BitOFF ; bit offset calculation | ||
| 56 | page | ||
| 57 | ;****************************************************************************** | ||
| 58 | ; L O C A L C O N S T A N T S | ||
| 59 | ;****************************************************************************** | ||
| 60 | ; | ||
| 61 | include VDMseg.inc | ||
| 62 | include VDMsel.inc | ||
| 63 | include desc.inc | ||
| 64 | include elim.inc | ||
| 65 | FALSE equ 0 | ||
| 66 | TRUE equ not FALSE | ||
| 67 | |||
| 68 | page | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; E X T E R N A L R E F E R E N C E S | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; | ||
| 73 | ABS0 segment at 0000h | ||
| 74 | ABS0 ends | ||
| 75 | |||
| 76 | TSS segment | ||
| 77 | |||
| 78 | extrn IOBitMap:byte ; Bit Map in Tss | ||
| 79 | |||
| 80 | TSS ends | ||
| 81 | |||
| 82 | |||
| 83 | _TEXT segment | ||
| 84 | |||
| 85 | extrn A20_Trap_Init:near ; (a20trap.asm) | ||
| 86 | extrn RR_Trap_Init:near ; (RRtrap.asm) | ||
| 87 | extrn OEM_Trap_Init:near ; (OEMProc.asm) | ||
| 88 | |||
| 89 | _TEXT ends | ||
| 90 | ; | ||
| 91 | ; | ||
| 92 | ;****************************************************************************** | ||
| 93 | ; L O C A L D A T A A R E A | ||
| 94 | ;****************************************************************************** | ||
| 95 | ; | ||
| 96 | _DATA segment | ||
| 97 | ; | ||
| 98 | _DATA ends | ||
| 99 | |||
| 100 | ; | ||
| 101 | ;****************************************************************************** | ||
| 102 | ; S E G M E N T D E F I N I T I O N | ||
| 103 | ;****************************************************************************** | ||
| 104 | ; | ||
| 105 | ;------------------------------------------------------------------------------ | ||
| 106 | _TEXT segment | ||
| 107 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 108 | vminit label byte | ||
| 109 | page | ||
| 110 | ;****************************************************************************** | ||
| 111 | ; InitBitMap - Initialize 386 Tss I/O bit map for Virtual mode I/O trapping. | ||
| 112 | ; | ||
| 113 | ; ENTRY: Real Mode | ||
| 114 | ; DS = DGROUP | ||
| 115 | ; I/O bit map all zeroes (no trapping) except last byte. | ||
| 116 | ; EXIT: Real Mode | ||
| 117 | ; I/O bit map in Tss initialized. | ||
| 118 | ; USED: Flags | ||
| 119 | ; STACK: | ||
| 120 | ;------------------------------------------------------------------------------ | ||
| 121 | InitBitMap proc far | ||
| 122 | ; | ||
| 123 | push ax | ||
| 124 | push bx | ||
| 125 | push si | ||
| 126 | push es | ||
| 127 | ; | ||
| 128 | mov ax,seg TSS | ||
| 129 | mov es,ax ; set ES to I/O Bit Map seg | ||
| 130 | ASSUME ES:TSS | ||
| 131 | xor bx,bx ; ES:[BX] = pts to TSS | ||
| 132 | ; | ||
| 133 | ; initialize BitMapBase in Tss | ||
| 134 | ; | ||
| 135 | mov ax,offset TSS:IOBitMap | ||
| 136 | mov ES:[bx.BitMapBase],ax ; set Bit Map base in Tss | ||
| 137 | ; | ||
| 138 | ; set ports for return to real trap | ||
| 139 | ; | ||
| 140 | call RR_Trap_Init | ||
| 141 | ; | ||
| 142 | ; Turn on Keyboard watching for A20 disable | ||
| 143 | ; | ||
| 144 | call A20_Trap_Init | ||
| 145 | ; | ||
| 146 | ; Turn on any other OEM specific trapping | ||
| 147 | ; | ||
| 148 | call OEM_Trap_Init | ||
| 149 | |||
| 150 | IB_exit: | ||
| 151 | pop es | ||
| 152 | ASSUME ES:DGROUP | ||
| 153 | pop si | ||
| 154 | pop bx | ||
| 155 | pop ax | ||
| 156 | ret ; *** RETURN *** | ||
| 157 | InitBitMap endp | ||
| 158 | |||
| 159 | ;****************************************************************************** | ||
| 160 | ; PortTrap - sets bit(s) in I/O bit map to enable trapping at an I/O address | ||
| 161 | ; | ||
| 162 | ; This function sets the appropriate bits in the I/O bit map to enable | ||
| 163 | ; trapping of the desired I/O address. Since some I/O ports on the AT system | ||
| 164 | ; board are selected via only 10 bits of address lines, these ports appear | ||
| 165 | ; at every 1K in the I/O address space. When trapping these "system board" | ||
| 166 | ; ports, the trap bits in the I/O bit map must be set for every 1k instance | ||
| 167 | ; of the port. | ||
| 168 | ; | ||
| 169 | ; ENTRY: AX = byte I/O address to set in Bit Map | ||
| 170 | ; BH = high bit set => set traps bits for this address @ every 1K | ||
| 171 | ; ES = TSS | ||
| 172 | ; | ||
| 173 | ; EXIT: none. | ||
| 174 | ; | ||
| 175 | ; USED: Flags | ||
| 176 | ; STACK: | ||
| 177 | ;------------------------------------------------------------------------------ | ||
| 178 | PortTrap proc near | ||
| 179 | ; | ||
| 180 | ASSUME ES:TSS | ||
| 181 | push ax | ||
| 182 | push bx | ||
| 183 | push cx | ||
| 184 | ; | ||
| 185 | mov cx,1 ; once by default | ||
| 186 | test bh,80h ;Q: map it every 1K ? | ||
| 187 | jz PT_loop ; N: do it once | ||
| 188 | mov cx,64 ; Y: do it 64 times (once per 1k) | ||
| 189 | PT_loop: | ||
| 190 | push ax ; map it. save this address | ||
| 191 | call BitOFF ; get offset and bit | ||
| 192 | or ES:IOBitMap[bx],al ; trap this address | ||
| 193 | pop ax ; restore this address | ||
| 194 | add ax,400h ; add 1k for next address | ||
| 195 | loop PT_loop ; and continue ... | ||
| 196 | ; | ||
| 197 | pop cx | ||
| 198 | pop bx | ||
| 199 | pop ax | ||
| 200 | ret | ||
| 201 | ASSUME ES:DGROUP | ||
| 202 | ; | ||
| 203 | PortTrap endp | ||
| 204 | |||
| 205 | |||
| 206 | ifdef oldstuff | ||
| 207 | ;****************************************************************************** | ||
| 208 | ; PortClear - clears bit(s) in I/O bit map to disable trapping at an I/O | ||
| 209 | ; address | ||
| 210 | ; | ||
| 211 | ; This function clears the appropriate bits in the I/O bit map to disable | ||
| 212 | ; trapping of the desired I/O address. Since some I/O ports on the AT system | ||
| 213 | ; board are selected via only 10 bits of address lines, these ports appear | ||
| 214 | ; at every 1K in the I/O address space. When clearing these "system board" | ||
| 215 | ; ports, the trap bits in the I/O bit map must be cleared at every 1k instance | ||
| 216 | ; of the port. | ||
| 217 | ; | ||
| 218 | ; ENTRY: AX = byte I/O address to clear in Bit Map | ||
| 219 | ; BH = high bit set => clear traps bits for this address @ every 1K | ||
| 220 | ; ES = data segment for I/O bit map | ||
| 221 | ; | ||
| 222 | ; EXIT: none. | ||
| 223 | ; | ||
| 224 | ; USED: Flags | ||
| 225 | ; STACK: | ||
| 226 | ; NOTE: This implementation does not account for a port being multiply set | ||
| 227 | ; for many purposes. (ie. If a port is set 3 times, it still only takes one | ||
| 228 | ; PortClear call to clear it.) If this is a problem, a counter for each | ||
| 229 | ; enabled port will have to be added. | ||
| 230 | ; | ||
| 231 | ;------------------------------------------------------------------------------ | ||
| 232 | PortClear proc near | ||
| 233 | ; | ||
| 234 | ASSUME ES:TSS | ||
| 235 | push ax | ||
| 236 | push bx | ||
| 237 | push cx | ||
| 238 | ; | ||
| 239 | mov cx,1 ; once by default | ||
| 240 | test bh,80h ;Q: map it every 1K ? | ||
| 241 | jz PC_loop ; N: do it once | ||
| 242 | mov cx,64 ; Y: do it 64 times (once per 1k) | ||
| 243 | PC_loop: | ||
| 244 | push ax ; map it. save this address | ||
| 245 | call BitOFF ; get offset and bit | ||
| 246 | not al | ||
| 247 | and ES:IOBitMap[bx],al ; clear this address | ||
| 248 | pop ax ; restore this address | ||
| 249 | add ax,400h ; add 1k for next address | ||
| 250 | loop PC_loop ; and continue ... | ||
| 251 | ; | ||
| 252 | pop cx | ||
| 253 | pop bx | ||
| 254 | pop ax | ||
| 255 | ret | ||
| 256 | ASSUME ES:DGROUP | ||
| 257 | ; | ||
| 258 | PortClear endp | ||
| 259 | endif ; oldstuff | ||
| 260 | |||
| 261 | |||
| 262 | ;****************************************************************************** | ||
| 263 | ; BitOFF - sets up byte and bit for I/O address in I/O Bit Map | ||
| 264 | ; | ||
| 265 | ; ENTRY: AX = byte I/O address to set in Bit Map | ||
| 266 | ; | ||
| 267 | ; EXIT: BX = byte offset | ||
| 268 | ; AL = bit to OR in to set proper bit | ||
| 269 | ; | ||
| 270 | ; USED: Flags | ||
| 271 | ; STACK: | ||
| 272 | ;------------------------------------------------------------------------------ | ||
| 273 | BitOFF proc near | ||
| 274 | ; | ||
| 275 | push cx | ||
| 276 | |||
| 277 | mov cx,ax | ||
| 278 | and cx,07h ; CL = bit pos for this port | ||
| 279 | shr ax,3 ; AX = byte offset for this bit | ||
| 280 | mov bx,ax ; BX = byte offset for port | ||
| 281 | mov ax,1 | ||
| 282 | shl ax,cl ; AL = bit mask for this port | ||
| 283 | |||
| 284 | pop cx | ||
| 285 | ret | ||
| 286 | ; | ||
| 287 | BitOFF endp | ||
| 288 | |||
| 289 | ; | ||
| 290 | _TEXT ends ; end of segment | ||
| 291 | ; | ||
| 292 | end ; end of module | ||
diff --git a/v4.0/src/MEMM/MEMM/VMINST.ASM b/v4.0/src/MEMM/MEMM/VMINST.ASM new file mode 100644 index 0000000..9b1a5c7 --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VMINST.ASM | |||
| @@ -0,0 +1,2135 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VMINST.ASM - Virtual Mode GP fault instruction emulation | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VMINST.ASM - Virtual Mode GP fault instruction emulation | ||
| 13 | ; | ||
| 14 | ; Version: 0.07 | ||
| 15 | ; | ||
| 16 | ; Date: February 11, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------- | ||
| 26 | ; 02/12/86 Original | ||
| 27 | ; 04/07/86 A- Added call to LIM emulation routines for all I/O. | ||
| 28 | ; Bit Map set up to trap only LIM related ports. SBP. | ||
| 29 | ; 05/12/86 B Cleanup and segment reorganization | ||
| 30 | ; 05/18/86 C Added VM privileged instruction emulation | ||
| 31 | ; 06/08/86 D Added calls to RRTrap. | ||
| 32 | ; 06/14/86 E Changed stack saves from BP, BX, SI to EBP, EBX, ESI | ||
| 33 | ; 06/15/86 F Changed inc [bp.VTFOE+VMTF_EIP] to inc SI in Prefix | ||
| 34 | ; Handlers | ||
| 35 | ; 06/15/86 G Added MOVSB and MOVSW for Rash Rule emulation | ||
| 36 | ; 06/16/86 H Added Error Handler interfaces, BugMode conditional | ||
| 37 | ; assembly constructs, and Error Handler return logic | ||
| 38 | ; 06/19/86 0.01 Changed call JumpReal to jmp JumpReal | ||
| 39 | ; 06/19/86 0.01 Clear TF bit on all INT reflects, but not on emulations. | ||
| 40 | ; 06/19/86 0.01 CLTS now does a clts for the VM client. | ||
| 41 | ; 06/27/86 0.02 INT3 emulation now ALLWAYS reflects | ||
| 42 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 43 | ; 07/01/86 0.03 Call to IO_Trap instead of LIM_Trap | ||
| 44 | ; 07/03/86 0.03 Let IO_Trap handle A20 and Return to real logic | ||
| 45 | ; 07/05/86 0.04 JumpReal in R_CODE | ||
| 46 | ; 07/06/86 0.04 changed assume to DGROUP | ||
| 47 | ; 07/10/86 0.05 added MB_Flag check for move block emulator | ||
| 48 | ; 07/30/86 0.06 removed PortClear reference | ||
| 49 | ; 08/05/86 0.07 Changed EmHalt to really HLT if user IF=0 | ||
| 50 | ; 07/20/88 Removed debugger codes (pc) | ||
| 51 | ; | ||
| 52 | ;****************************************************************************** | ||
| 53 | ; | ||
| 54 | ; Functional Description: | ||
| 55 | ; | ||
| 56 | ; This module contains the routines that handle GP faults fielded from | ||
| 57 | ; Virtual Mode. The offending instruction is either emulated or we exit | ||
| 58 | ; to the debugger. | ||
| 59 | ; | ||
| 60 | ; NOTE: The current implementation is sufficient for breadboard - see | ||
| 61 | ; 'to do' notes in various header for holes. Specifically, the only | ||
| 62 | ; override that is handled is REP, and only for INS/OUTS. Segment | ||
| 63 | ; overrides are not yet supported. | ||
| 64 | ; | ||
| 65 | ;****************************************************************************** | ||
| 66 | .lfcond ; list false conditionals | ||
| 67 | .386p | ||
| 68 | page | ||
| 69 | ;****************************************************************************** | ||
| 70 | ; P U B L I C D E C L A R A T I O N S | ||
| 71 | ;****************************************************************************** | ||
| 72 | ; | ||
| 73 | public VmInst ; module label | ||
| 74 | public VmFault | ||
| 75 | public EmProtIns ; just for debug map | ||
| 76 | public EmMovCDTR ; just for debug map | ||
| 77 | public EmMOVSW ; just for debug map | ||
| 78 | ; | ||
| 79 | ;****************************************************************************** | ||
| 80 | ; E X T E R N A L R E F E R E N C E S | ||
| 81 | ;****************************************************************************** | ||
| 82 | ; | ||
| 83 | R_CODE segment | ||
| 84 | extrn JumpReal:far ; cont client in RM (rrtrap.asm) | ||
| 85 | extrn MB_Flag:byte ; non-zero => do move block | ||
| 86 | R_CODE ends | ||
| 87 | |||
| 88 | _TEXT segment | ||
| 89 | extrn IO_Trap:near ; I/O Trap Dispatcher | ||
| 90 | extrn EM286ll:near ; 286 loadall emulator (EM286LL) | ||
| 91 | extrn EM386ll:near ; 386 loadall emulator (EM386LL) | ||
| 92 | extrn Move_Block:near ; Int 15h move block function (MOVEB) | ||
| 93 | extrn hw_int:near ; HW-ROM reflection code (VMTRAP) | ||
| 94 | extrn ErrHndlr:near ; Handle user's error response | ||
| 95 | extrn MapLinear:near ; map linear address | ||
| 96 | extrn UnMapLinear:near ; unmap linear address | ||
| 97 | _TEXT ends | ||
| 98 | |||
| 99 | page | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; I N C L U D E F I L E S | ||
| 102 | ;****************************************************************************** | ||
| 103 | |||
| 104 | include VDMseg.inc | ||
| 105 | include desc.inc | ||
| 106 | include VDMsel.inc | ||
| 107 | include vm386.inc | ||
| 108 | include loadall.inc | ||
| 109 | include instr386.inc | ||
| 110 | include oemdep.inc | ||
| 111 | ;****************************************************************************** | ||
| 112 | ; L O C A L C O N S T A N T S | ||
| 113 | ;****************************************************************************** | ||
| 114 | ; | ||
| 115 | FALSE equ 0 | ||
| 116 | TRUE equ not FALSE | ||
| 117 | |||
| 118 | LOCK_PREFIX equ 0F0h | ||
| 119 | |||
| 120 | IF_FLAG equ 0200h ; IF bit in flags | ||
| 121 | DF_FLAG equ 0400h ; DF bit in flags | ||
| 122 | |||
| 123 | ; | ||
| 124 | ; bit flags for instruction prefixes | ||
| 125 | ; | ||
| 126 | REP_FLAG equ 0001h | ||
| 127 | REPNE_FLAG equ 0002h | ||
| 128 | REPS_FLAG equ (REP_FLAG or REPNE_FLAG) | ||
| 129 | CS_FLAG equ 0004h | ||
| 130 | DS_FLAG equ 0008h | ||
| 131 | ES_FLAG equ 0010h | ||
| 132 | SS_FLAG equ 0020h | ||
| 133 | FS_FLAG equ 0040h | ||
| 134 | GS_FLAG equ 0080h | ||
| 135 | LOCK_FLAG equ 0100h | ||
| 136 | OPER_SZ_FLAG equ 0200h | ||
| 137 | ADDR_SZ_FLAG equ 0400h | ||
| 138 | P0F_FLAG equ 0800h | ||
| 139 | |||
| 140 | page | ||
| 141 | ;****************************************************************************** | ||
| 142 | ; L O C A L D A T A A R E A | ||
| 143 | ;****************************************************************************** | ||
| 144 | _DATA segment | ||
| 145 | |||
| 146 | PrefixFlag dw 0 ; flags for Fault Instr Prefixes | ||
| 147 | RefNum dw 0 ; Reflect number for RefToRom | ||
| 148 | |||
| 149 | _DATA ends | ||
| 150 | |||
| 151 | page | ||
| 152 | ;****************************************************************************** | ||
| 153 | ; C O D E A R E A | ||
| 154 | ;****************************************************************************** | ||
| 155 | _TEXT segment | ||
| 156 | assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:DGROUP | ||
| 157 | |||
| 158 | VmInst label byte | ||
| 159 | ; | ||
| 160 | ; Index table for opcode emulation dispatch - This is too general-purpose | ||
| 161 | ; if all we want to handle is INT instructions, but it'll get fleshed out | ||
| 162 | ; later, when we start emulating IOPL-sensitive stuff | ||
| 163 | ; | ||
| 164 | ; the directive below is giving problems because this segment is byte aligned | ||
| 165 | ; will fix it..sunilp | ||
| 166 | ; EVEN ; word aligning should make execution | ||
| 167 | ; faster | ||
| 168 | OpTable label word | ||
| 169 | dw offset _TEXT:BadVmTrap ; 0 - LLDT, LTR, SLDT, STR, VERR, VERW | ||
| 170 | dw offset _TEXT:EmProtIns ; 1 - LGDT, LIDT, LMSW | ||
| 171 | dw offset _TEXT:BadVmTrap ; 2 - LAR | ||
| 172 | dw offset _TEXT:BadVmTrap ; 3 - LSL | ||
| 173 | dw offset _TEXT:BadVmTrap ; 4 | ||
| 174 | dw offset _TEXT:EmLoadal2 ; 5 - 286Loadall | ||
| 175 | dw offset _TEXT:EmCLTS ; 6 - CLTS | ||
| 176 | dw offset _TEXT:EmLoadal3 ; 7 - 386Loadall | ||
| 177 | dw offset _TEXT:BadVmTrap ; 8 | ||
| 178 | dw offset _TEXT:BadVmTrap ; 9 | ||
| 179 | dw offset _TEXT:BadVmTrap ; a | ||
| 180 | dw offset _TEXT:BadVmTrap ; b | ||
| 181 | dw offset _TEXT:BadVmTrap ; c | ||
| 182 | dw offset _TEXT:BadVmTrap ; d | ||
| 183 | dw offset _TEXT:BadVmTrap ; e | ||
| 184 | dw offset _TEXT:Prefix_0F ; f | ||
| 185 | dw offset _TEXT:BadVmTrap ; 10 | ||
| 186 | dw offset _TEXT:BadVmTrap ; 11 | ||
| 187 | dw offset _TEXT:BadVmTrap ; 12 | ||
| 188 | dw offset _TEXT:BadVmTrap ; 13 | ||
| 189 | dw offset _TEXT:BadVmTrap ; 14 | ||
| 190 | dw offset _TEXT:BadVmTrap ; 15 | ||
| 191 | dw offset _TEXT:BadVmTrap ; 16 | ||
| 192 | dw offset _TEXT:BadVmTrap ; 17 | ||
| 193 | dw offset _TEXT:BadVmTrap ; 18 | ||
| 194 | dw offset _TEXT:BadVmTrap ; 19 | ||
| 195 | dw offset _TEXT:BadVmTrap ; 1a | ||
| 196 | dw offset _TEXT:BadVmTrap ; 1b | ||
| 197 | dw offset _TEXT:BadVmTrap ; 1c | ||
| 198 | dw offset _TEXT:BadVmTrap ; 1d | ||
| 199 | dw offset _TEXT:BadVmTrap ; 1e | ||
| 200 | dw offset _TEXT:BadVmTrap ; 1f | ||
| 201 | dw offset _TEXT:EmMovCDTR ; 20 - Mov Rn, CRn | ||
| 202 | dw offset _TEXT:EmMovCDTR ; 21 - Mov Rn, DRn | ||
| 203 | dw offset _TEXT:EmMovCDTR ; 22 - Mov CRn, Rn | ||
| 204 | dw offset _TEXT:EmMovCDTR ; 23 - Mov DRn, Rn | ||
| 205 | dw offset _TEXT:EmMovCDTR ; 24 - Mov Rn, TRn | ||
| 206 | dw offset _TEXT:BadVmTrap ; 25 | ||
| 207 | dw offset _TEXT:ESOverride ; 26 - ES Override & Mov TRn, Rn | ||
| 208 | dw offset _TEXT:BadVmTrap ; 27 | ||
| 209 | dw offset _TEXT:BadVmTrap ; 28 | ||
| 210 | dw offset _TEXT:BadVmTrap ; 29 | ||
| 211 | dw offset _TEXT:BadVmTrap ; 2a | ||
| 212 | dw offset _TEXT:BadVmTrap ; 2b | ||
| 213 | dw offset _TEXT:BadVmTrap ; 2c | ||
| 214 | dw offset _TEXT:BadVmTrap ; 2d | ||
| 215 | dw offset _TEXT:CSOverride ; 2e - CS Override | ||
| 216 | dw offset _TEXT:BadVmTrap ; 2f | ||
| 217 | dw offset _TEXT:BadVmTrap ; 30 | ||
| 218 | dw offset _TEXT:BadVmTrap ; 31 | ||
| 219 | dw offset _TEXT:BadVmTrap ; 32 | ||
| 220 | dw offset _TEXT:BadVmTrap ; 33 | ||
| 221 | dw offset _TEXT:BadVmTrap ; 34 | ||
| 222 | dw offset _TEXT:BadVmTrap ; 35 | ||
| 223 | dw offset _TEXT:SSOverride ; 36 - SS Override | ||
| 224 | dw offset _TEXT:BadVmTrap ; 37 | ||
| 225 | dw offset _TEXT:BadVmTrap ; 38 | ||
| 226 | dw offset _TEXT:BadVmTrap ; 39 | ||
| 227 | dw offset _TEXT:BadVmTrap ; 3a | ||
| 228 | dw offset _TEXT:BadVmTrap ; 3b | ||
| 229 | dw offset _TEXT:BadVmTrap ; 3c | ||
| 230 | dw offset _TEXT:BadVmTrap ; 3d | ||
| 231 | dw offset _TEXT:DSOverride ; 3e - DS Override | ||
| 232 | dw offset _TEXT:BadVmTrap ; 3f | ||
| 233 | dw offset _TEXT:BadVmTrap ; 40 | ||
| 234 | dw offset _TEXT:BadVmTrap ; 41 | ||
| 235 | dw offset _TEXT:BadVmTrap ; 42 | ||
| 236 | dw offset _TEXT:BadVmTrap ; 43 | ||
| 237 | dw offset _TEXT:BadVmTrap ; 44 | ||
| 238 | dw offset _TEXT:BadVmTrap ; 45 | ||
| 239 | dw offset _TEXT:BadVmTrap ; 46 | ||
| 240 | dw offset _TEXT:BadVmTrap ; 47 | ||
| 241 | dw offset _TEXT:BadVmTrap ; 48 | ||
| 242 | dw offset _TEXT:BadVmTrap ; 49 | ||
| 243 | dw offset _TEXT:BadVmTrap ; 4a | ||
| 244 | dw offset _TEXT:BadVmTrap ; 4b | ||
| 245 | dw offset _TEXT:BadVmTrap ; 4c | ||
| 246 | dw offset _TEXT:BadVmTrap ; 4d | ||
| 247 | dw offset _TEXT:BadVmTrap ; 4e | ||
| 248 | dw offset _TEXT:BadVmTrap ; 4f | ||
| 249 | dw offset _TEXT:BadVmTrap ; 50 | ||
| 250 | dw offset _TEXT:BadVmTrap ; 51 | ||
| 251 | dw offset _TEXT:BadVmTrap ; 52 | ||
| 252 | dw offset _TEXT:BadVmTrap ; 53 | ||
| 253 | dw offset _TEXT:BadVmTrap ; 54 | ||
| 254 | dw offset _TEXT:BadVmTrap ; 55 | ||
| 255 | dw offset _TEXT:BadVmTrap ; 56 | ||
| 256 | dw offset _TEXT:BadVmTrap ; 57 | ||
| 257 | dw offset _TEXT:BadVmTrap ; 58 | ||
| 258 | dw offset _TEXT:BadVmTrap ; 59 | ||
| 259 | dw offset _TEXT:BadVmTrap ; 5a | ||
| 260 | dw offset _TEXT:BadVmTrap ; 5b | ||
| 261 | dw offset _TEXT:BadVmTrap ; 5c | ||
| 262 | dw offset _TEXT:BadVmTrap ; 5d | ||
| 263 | dw offset _TEXT:BadVmTrap ; 5e | ||
| 264 | dw offset _TEXT:BadVmTrap ; 5f | ||
| 265 | dw offset _TEXT:BadVmTrap ; 60 | ||
| 266 | dw offset _TEXT:BadVmTrap ; 61 | ||
| 267 | dw offset _TEXT:BadVmTrap ; 62 | ||
| 268 | ; | ||
| 269 | ; ARPL is used to return from virtual mode to protected mode for use in MEMM | ||
| 270 | ; | ||
| 271 | dw offset _TEXT:ReturnEMM ; 63 - ARPL (return to Protected mode gateway) | ||
| 272 | dw offset _TEXT:FSOverride ; 64 - FS override | ||
| 273 | dw offset _TEXT:GSOverride ; 65 - GS override | ||
| 274 | dw offset _TEXT:BadVmTrap ; 66 - Operand size override | ||
| 275 | dw offset _TEXT:BadVmTrap ; 67 - Address size override | ||
| 276 | dw offset _TEXT:BadVmTrap ; 68 | ||
| 277 | dw offset _TEXT:BadVmTrap ; 69 | ||
| 278 | dw offset _TEXT:BadVmTrap ; 6a | ||
| 279 | dw offset _TEXT:BadVmTrap ; 6b | ||
| 280 | dw offset _TEXT:EmINSB ; 6c - INSB | ||
| 281 | dw offset _TEXT:EmINSW ; 6d - INSW | ||
| 282 | dw offset _TEXT:EmOUTSB ; 6e - OUTSB | ||
| 283 | dw offset _TEXT:EmOUTSW ; 6f - OUTSW | ||
| 284 | dw offset _TEXT:BadVmTrap ; 70 | ||
| 285 | dw offset _TEXT:BadVmTrap ; 71 | ||
| 286 | dw offset _TEXT:BadVmTrap ; 72 | ||
| 287 | dw offset _TEXT:BadVmTrap ; 73 | ||
| 288 | dw offset _TEXT:BadVmTrap ; 74 | ||
| 289 | dw offset _TEXT:BadVmTrap ; 75 | ||
| 290 | dw offset _TEXT:BadVmTrap ; 76 | ||
| 291 | dw offset _TEXT:BadVmTrap ; 77 | ||
| 292 | dw offset _TEXT:BadVmTrap ; 78 | ||
| 293 | dw offset _TEXT:BadVmTrap ; 79 | ||
| 294 | dw offset _TEXT:BadVmTrap ; 7a | ||
| 295 | dw offset _TEXT:BadVmTrap ; 7b | ||
| 296 | dw offset _TEXT:BadVmTrap ; 7c | ||
| 297 | dw offset _TEXT:BadVmTrap ; 7d | ||
| 298 | dw offset _TEXT:BadVmTrap ; 7e | ||
| 299 | dw offset _TEXT:BadVmTrap ; 7f | ||
| 300 | dw offset _TEXT:BadVmTrap ; 80 | ||
| 301 | dw offset _TEXT:BadVmTrap ; 81 | ||
| 302 | dw offset _TEXT:BadVmTrap ; 82 | ||
| 303 | dw offset _TEXT:BadVmTrap ; 83 | ||
| 304 | dw offset _TEXT:BadVmTrap ; 84 | ||
| 305 | dw offset _TEXT:BadVmTrap ; 85 | ||
| 306 | dw offset _TEXT:BadVmTrap ; 86 | ||
| 307 | dw offset _TEXT:BadVmTrap ; 87 | ||
| 308 | dw offset _TEXT:BadVmTrap ; 88 | ||
| 309 | dw offset _TEXT:BadVmTrap ; 89 | ||
| 310 | dw offset _TEXT:BadVmTrap ; 8a | ||
| 311 | dw offset _TEXT:BadVmTrap ; 8b | ||
| 312 | dw offset _TEXT:BadVmTrap ; 8c | ||
| 313 | dw offset _TEXT:BadVmTrap ; 8d | ||
| 314 | dw offset _TEXT:BadVmTrap ; 8e | ||
| 315 | dw offset _TEXT:BadVmTrap ; 8f | ||
| 316 | dw offset _TEXT:BadVmTrap ; 90 | ||
| 317 | dw offset _TEXT:BadVmTrap ; 91 | ||
| 318 | dw offset _TEXT:BadVmTrap ; 92 | ||
| 319 | dw offset _TEXT:BadVmTrap ; 93 | ||
| 320 | dw offset _TEXT:BadVmTrap ; 94 | ||
| 321 | dw offset _TEXT:BadVmTrap ; 95 | ||
| 322 | dw offset _TEXT:BadVmTrap ; 96 | ||
| 323 | dw offset _TEXT:BadVmTrap ; 97 | ||
| 324 | dw offset _TEXT:BadVmTrap ; 98 | ||
| 325 | dw offset _TEXT:BadVmTrap ; 99 | ||
| 326 | dw offset _TEXT:BadVmTrap ; 9a | ||
| 327 | dw offset _TEXT:BadVmTrap ; 9b | ||
| 328 | dw offset _TEXT:BadVmTrap ; 9c - PUSHF (not for IOPL=3) | ||
| 329 | dw offset _TEXT:BadVmTrap ; 9d - POPF (not for IOPL=3) | ||
| 330 | dw offset _TEXT:BadVmTrap ; 9e | ||
| 331 | dw offset _TEXT:BadVmTrap ; 9f | ||
| 332 | dw offset _TEXT:BadVmTrap ; a0 | ||
| 333 | dw offset _TEXT:BadVmTrap ; a1 | ||
| 334 | dw offset _TEXT:BadVmTrap ; a2 | ||
| 335 | dw offset _TEXT:BadVmTrap ; a3 | ||
| 336 | dw offset _TEXT:BadVmTrap ; a4 - MOVSB | ||
| 337 | dw offset _TEXT:EmMOVSW ; a5 - MOVSW | ||
| 338 | dw offset _TEXT:BadVmTrap ; a6 | ||
| 339 | dw offset _TEXT:BadVmTrap ; a7 | ||
| 340 | dw offset _TEXT:BadVmTrap ; a8 | ||
| 341 | dw offset _TEXT:BadVmTrap ; a9 | ||
| 342 | dw offset _TEXT:BadVmTrap ; aa | ||
| 343 | dw offset _TEXT:BadVmTrap ; ab | ||
| 344 | dw offset _TEXT:BadVmTrap ; ac | ||
| 345 | dw offset _TEXT:BadVmTrap ; ad | ||
| 346 | dw offset _TEXT:BadVmTrap ; ae | ||
| 347 | dw offset _TEXT:BadVmTrap ; af | ||
| 348 | dw offset _TEXT:BadVmTrap ; b0 | ||
| 349 | dw offset _TEXT:BadVmTrap ; b1 | ||
| 350 | dw offset _TEXT:BadVmTrap ; b2 | ||
| 351 | dw offset _TEXT:BadVmTrap ; b3 | ||
| 352 | dw offset _TEXT:BadVmTrap ; b4 | ||
| 353 | dw offset _TEXT:BadVmTrap ; b5 | ||
| 354 | dw offset _TEXT:BadVmTrap ; b6 | ||
| 355 | dw offset _TEXT:BadVmTrap ; b7 | ||
| 356 | dw offset _TEXT:BadVmTrap ; b8 | ||
| 357 | dw offset _TEXT:BadVmTrap ; b9 | ||
| 358 | dw offset _TEXT:BadVmTrap ; ba | ||
| 359 | dw offset _TEXT:BadVmTrap ; bb | ||
| 360 | dw offset _TEXT:BadVmTrap ; bc | ||
| 361 | dw offset _TEXT:BadVmTrap ; bd | ||
| 362 | dw offset _TEXT:BadVmTrap ; be | ||
| 363 | dw offset _TEXT:BadVmTrap ; bf | ||
| 364 | dw offset _TEXT:BadVmTrap ; c0 | ||
| 365 | dw offset _TEXT:BadVmTrap ; c1 | ||
| 366 | dw offset _TEXT:BadVmTrap ; c2 | ||
| 367 | dw offset _TEXT:BadVmTrap ; c3 | ||
| 368 | dw offset _TEXT:BadVmTrap ; c4 | ||
| 369 | dw offset _TEXT:BadVmTrap ; c5 | ||
| 370 | dw offset _TEXT:BadVmTrap ; c6 | ||
| 371 | dw offset _TEXT:BadVmTrap ; c7 | ||
| 372 | dw offset _TEXT:BadVmTrap ; c8 | ||
| 373 | dw offset _TEXT:BadVmTrap ; c9 | ||
| 374 | dw offset _TEXT:BadVmTrap ; ca | ||
| 375 | dw offset _TEXT:BadVmTrap ; cb | ||
| 376 | dw offset _TEXT:EmINT3 ; cc - INT 3 | ||
| 377 | dw offset _TEXT:EmINTnn ; cd - INT nn | ||
| 378 | dw offset _TEXT:EmINTO ; ce - INTO | ||
| 379 | dw offset _TEXT:BadVmTrap ; cf - IRET/EmIRET (not for IOPL=3) | ||
| 380 | dw offset _TEXT:BadVmTrap ; d0 | ||
| 381 | dw offset _TEXT:BadVmTrap ; d1 | ||
| 382 | dw offset _TEXT:BadVmTrap ; d2 | ||
| 383 | dw offset _TEXT:BadVmTrap ; d3 | ||
| 384 | dw offset _TEXT:BadVmTrap ; d4 | ||
| 385 | dw offset _TEXT:BadVmTrap ; d5 | ||
| 386 | dw offset _TEXT:BadVmTrap ; d6 | ||
| 387 | dw offset _TEXT:BadVmTrap ; d7 | ||
| 388 | dw offset _TEXT:BadVmTrap ; d8 | ||
| 389 | dw offset _TEXT:BadVmTrap ; d9 | ||
| 390 | dw offset _TEXT:BadVmTrap ; da | ||
| 391 | dw offset _TEXT:BadVmTrap ; db | ||
| 392 | dw offset _TEXT:BadVmTrap ; dc | ||
| 393 | dw offset _TEXT:BadVmTrap ; dd | ||
| 394 | dw offset _TEXT:BadVmTrap ; de | ||
| 395 | dw offset _TEXT:BadVmTrap ; df | ||
| 396 | dw offset _TEXT:BadVmTrap ; e0 | ||
| 397 | dw offset _TEXT:BadVmTrap ; e1 | ||
| 398 | dw offset _TEXT:BadVmTrap ; e2 | ||
| 399 | dw offset _TEXT:BadVmTrap ; e3 | ||
| 400 | dw offset _TEXT:EmINBimm ; e4 - INB imm | ||
| 401 | dw offset _TEXT:EmINWimm ; e5 - INW imm | ||
| 402 | dw offset _TEXT:EmOUTBimm ; e6 - OUTB imm | ||
| 403 | dw offset _TEXT:EmOUTWimm ; e7 - OUTW imm | ||
| 404 | dw offset _TEXT:BadVmTrap ; e8 | ||
| 405 | dw offset _TEXT:BadVmTrap ; e9 | ||
| 406 | dw offset _TEXT:BadVmTrap ; ea | ||
| 407 | dw offset _TEXT:BadVmTrap ; eb | ||
| 408 | dw offset _TEXT:EmINB ; ec - INB | ||
| 409 | dw offset _TEXT:EmINW ; ed - INW | ||
| 410 | dw offset _TEXT:EmOUTB ; ee - OUTB | ||
| 411 | dw offset _TEXT:EmOUTW ; ef - OUTW | ||
| 412 | dw offset _TEXT:EmLOCK ; f0 - LOCK | ||
| 413 | dw offset _TEXT:BadVmTrap ; f1 | ||
| 414 | dw offset _TEXT:EmREPNE ; f2 - REPNE | ||
| 415 | dw offset _TEXT:EmREP ; f3 - REP/REPE | ||
| 416 | dw offset _TEXT:EmHALT ; f4 - HLT | ||
| 417 | dw offset _TEXT:BadVmTrap ; f5 | ||
| 418 | dw offset _TEXT:BadVmTrap ; f6 | ||
| 419 | dw offset _TEXT:BadVmTrap ; f7 | ||
| 420 | dw offset _TEXT:BadVmTrap ; f8 | ||
| 421 | dw offset _TEXT:BadVmTrap ; f9 | ||
| 422 | dw offset _TEXT:BadVmTrap ; fa - CLI EmCLI (not for IOPL=3) | ||
| 423 | dw offset _TEXT:BadVmTrap ; fb - STI EmSTI (not for IOPL=3) | ||
| 424 | dw offset _TEXT:BadVmTrap ; fc | ||
| 425 | dw offset _TEXT:BadVmTrap ; fd | ||
| 426 | dw offset _TEXT:BadVmTrap ; fe | ||
| 427 | dw offset _TEXT:BadVmTrap ; ff - Change P0F_Invalid, if used | ||
| 428 | |||
| 429 | page | ||
| 430 | ;****************************************************************************** | ||
| 431 | ; VmFault - entry point for Virtual Mode GP faults (from routine vm_trap0d | ||
| 432 | ; in module VMTRAP.ASM). The appropriate instructions are emulated and | ||
| 433 | ; control is returned to the Virtual Mode client. Currently, we assume | ||
| 434 | ; the client is running WITH IOPL, INT gate DPL = 0, and a truncated | ||
| 435 | ; IDT, so INT instruction fault to here and are emulated. All other | ||
| 436 | ; GP faults enter the debugger. | ||
| 437 | ; | ||
| 438 | ; The following instructions are invalid in Real or Virtual Mode: | ||
| 439 | ; | ||
| 440 | ; ARPL, LAR, LSL, VERR, VERW, STR, LTR, SLDT, LLDT | ||
| 441 | ; | ||
| 442 | ; The following instructions are privileged and are thus invalid in | ||
| 443 | ; Virtual Mode since VM progs run at CPL 3: | ||
| 444 | ; | ||
| 445 | ; LIDT, LDGT, LMSW, CLTS, HLT, Debug Register ops, Control | ||
| 446 | ; Register ops, and Test Register ops | ||
| 447 | ; | ||
| 448 | ; If client does not have IOPL, the following instructions must be handled | ||
| 449 | ; (in addition to the INT instructions). This scenario changes for B0: | ||
| 450 | ; | ||
| 451 | ; IN, INS, OUT, OUTS, STI, CLI, LOCK, PUSHF, POPF, and IRET | ||
| 452 | ; | ||
| 453 | ; For B0, the following instructions must be handled when they trap | ||
| 454 | ; according to the bit map in the TSS. | ||
| 455 | ; | ||
| 456 | ; IN, INS, OUT, and OUTS | ||
| 457 | ; | ||
| 458 | ; For Invalid Opcode (vm_trap06) emulation: | ||
| 459 | ; The following instructions are invalid in Real or Virtual Mode: | ||
| 460 | ; | ||
| 461 | ; LTR, LLDT, LAR, LSL, ARPL, STR, SLDT, VERR, VERW | ||
| 462 | ; | ||
| 463 | ; In fielding the exception from Virtual Mode, the 386 interrupt gate | ||
| 464 | ; switched to the Ring 0 stack and pushed 32-bit values as follows: | ||
| 465 | ; | ||
| 466 | ; hiword loword offset (in addition to error code and BP push) | ||
| 467 | ; +------+------+ <-------- Top of 'kernel' stack | ||
| 468 | ; | 0000 | GS | +32 (decimal) | ||
| 469 | ; |------+------| | ||
| 470 | ; | 0000 | FS | +28 | ||
| 471 | ; |------|------| | ||
| 472 | ; | 0000 | DS | +24 | ||
| 473 | ; |------|------| | ||
| 474 | ; | 0000 | ES | +20 | ||
| 475 | ; |------|------| | ||
| 476 | ; | 0000 | SS | +16 | ||
| 477 | ; |------|------| | ||
| 478 | ; | ESP | +12 | ||
| 479 | ; |------|------| | ||
| 480 | ; | EFLAGS | +08 | ||
| 481 | ; |------|------| | ||
| 482 | ; | 0000 | CS | +04 | ||
| 483 | ; |------|------| | ||
| 484 | ; | EIP | +00 | ||
| 485 | ; +------|------+ | ||
| 486 | ; | error code | | ||
| 487 | ; |------|------| <-------- Ring 0 SS:SP | ||
| 488 | ; | (ebp) | | ||
| 489 | ; +------+------+ <-------- Ring 0 SS:EBP | ||
| 490 | ; | ||
| 491 | ; | ||
| 492 | ; ENTRY: 386 Protected Mode - ring 0 | ||
| 493 | ; EBP is on the stack | ||
| 494 | ; SS:BP -> VM trap frame on stack w/error code (faulting selector) | ||
| 495 | ; GP exceptions are faults: pushed CS:EIP points to faulting opcode | ||
| 496 | ; EXIT: via IRET to VM client, instruction emulated as necessary | ||
| 497 | ; USED: (none) (note that DS & ES are free to use - saved during trap) | ||
| 498 | ; STACK: n/a | ||
| 499 | ;------------------------------------------------------------------------------ | ||
| 500 | VmFault proc near | ||
| 501 | PUSH_EBX ; local registers | ||
| 502 | PUSH_ESI | ||
| 503 | HwTabUnlock ; unlock high ram for gdt changes | ||
| 504 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 505 | mov ds,bx ; DS -> GDT | ||
| 506 | ; | ||
| 507 | ; Build a selector (VM1_GSEL) to client's stack. VM1_GSEL is already set | ||
| 508 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 509 | ; | ||
| 510 | mov bx,[bp.VTFOE+VMTF_SS] ; BX = VM SS (segment form) | ||
| 511 | shl bx,4 ; BX = low 16 bits of base | ||
| 512 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 513 | mov bx,[bp.VTFOE+VMTF_SS] ; BX = VM SS (again) | ||
| 514 | shr bx,4 ; BH = high 8 bits of base | ||
| 515 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 516 | ; | ||
| 517 | ; Build a selector (VM2_GSEL) to client's code segment, as above. | ||
| 518 | ; | ||
| 519 | mov bx,[bp.VTFOE+VMTF_CS] ; BX = VM CS (in segment form) | ||
| 520 | shl bx,4 ; BX = low 16 bits of base | ||
| 521 | mov ds:[VM2_GSEL+2],bx ; place in descriptor | ||
| 522 | mov bx,[bp.VTFOE+VMTF_CS] ; BX = VM CS (again) | ||
| 523 | shr bx,4 ; BH = high 8 bits of base | ||
| 524 | mov ds:[VM2_GSEL+4],bh ; place in descriptor | ||
| 525 | ; | ||
| 526 | ; Reset prefix flags | ||
| 527 | ; | ||
| 528 | mov bx,VDMD_GSEL | ||
| 529 | mov es,bx | ||
| 530 | mov ES:[PrefixFlag],0 ; start with no prefixes | ||
| 531 | ; | ||
| 532 | ; Jump to appropriate instruction handler | ||
| 533 | ; | ||
| 534 | mov bx,VM2_GSEL | ||
| 535 | mov ds,bx ; DS = selector for VM code segment | ||
| 536 | mov si,[bp.VTFOE+VMTF_EIP] ; DS:SI = VM CS:IP | ||
| 537 | VmInsHandle: | ||
| 538 | mov bl,ds:[si] ; BL = opcode | ||
| 539 | mov bh,0 ; BX = opcode | ||
| 540 | shl bx,1 ; BX = BX*2 (word table) | ||
| 541 | ; DS:SI = VM CS:IP | ||
| 542 | ; ES pts to local data segment | ||
| 543 | ; VM1_GSEL pts to VM SS | ||
| 544 | ; VM2_GSEL pts to VM CS | ||
| 545 | jmp cs:OpTable[bx] ; enter instruction emulation routine | ||
| 546 | |||
| 547 | VmFault endp | ||
| 548 | |||
| 549 | page | ||
| 550 | ;****************************************************************************** | ||
| 551 | ; BadVmTrap - unsupported Virtual Mode GP exception - enter the debugger | ||
| 552 | ; | ||
| 553 | ; ENTRY: EBP,EBX,ESI are on the stack | ||
| 554 | ; EXIT: to the debugger | ||
| 555 | ; USED: | ||
| 556 | ; STACK: n/a | ||
| 557 | ;------------------------------------------------------------------------------ | ||
| 558 | BadVmTrap proc near | ||
| 559 | jmp Reflect6 ; Reflect to VM illegal opcode handler | ||
| 560 | BadVmTrap endp | ||
| 561 | |||
| 562 | page | ||
| 563 | ;****************************************************************************** | ||
| 564 | ; ReturnEMM - user is trying to go back into the protected mode via ARPL | ||
| 565 | ; | ||
| 566 | ; ENTRY: EBP,EBX,ESI are on the stack | ||
| 567 | ; EXIT: to the debugger | ||
| 568 | ; USED: | ||
| 569 | ; STACK: n/a | ||
| 570 | ;------------------------------------------------------------------------------ | ||
| 571 | ReturnEMM proc near | ||
| 572 | add si, 2 ; "IP" now points to instruction | ||
| 573 | push si ; after "ARPL reg,reg" | ||
| 574 | ret ; back in protected mode! | ||
| 575 | ReturnEMM endp | ||
| 576 | |||
| 577 | page | ||
| 578 | ;****************************************************************************** | ||
| 579 | ; EmINTnn - emulate software interrupt | ||
| 580 | ; | ||
| 581 | ; The emulation of the software INT instructions requires us to massage | ||
| 582 | ; the trap stack frame (see VmFault header) and build a 'real mode' | ||
| 583 | ; stack frame for the virtual mode client so that we can transfer | ||
| 584 | ; control to virtual mode at the address specified in the appropriate | ||
| 585 | ; real mode IDT vector. The client's IRET out of the interrupt routine | ||
| 586 | ; will proceed normally (assuming we're letting him run with IOPL = 3). | ||
| 587 | ; Since we're fielding the trap from Virtual Mode, we assume the high | ||
| 588 | ; word of ESP and EIP is 0000. | ||
| 589 | ; | ||
| 590 | ; +-------+ <-------- Client's current SS:SP | ||
| 591 | ; | Flags | +4 | ||
| 592 | ; |-------| | ||
| 593 | ; | CS | +2 | ||
| 594 | ; |-------| | ||
| 595 | ; | IP | +0 | ||
| 596 | ; +-------+ <-------- Client's SS:SP when we let him have control | ||
| 597 | ; | ||
| 598 | ; ENTRY: 386 Protected Mode | ||
| 599 | ; EBP,EBX,ESI pushed on stack | ||
| 600 | ; VM1_GSEL = VM client's stack segment | ||
| 601 | ; VM2_GSEL = VM client's code segment | ||
| 602 | ; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL) | ||
| 603 | ; EXIT: via IRET to VM client | ||
| 604 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 605 | ; USED: (none) | ||
| 606 | ; STACK: | ||
| 607 | ; | ||
| 608 | ; to do: Streamline this code - it's on the critical path | ||
| 609 | ; Decide about how to handle Trace Bit in general | ||
| 610 | ;------------------------------------------------------------------------------ | ||
| 611 | EmINTnn proc near | ||
| 612 | |||
| 613 | inc si ; DS:SI -> nn (int #) | ||
| 614 | |||
| 615 | ; Check for Int15 (Move Block call) | ||
| 616 | cmp byte ptr [si], 15h | ||
| 617 | jne NotInt15 | ||
| 618 | cmp ah,87h ;Q: is this a move block call ? | ||
| 619 | jne NotInt15 ; N: process as normal interrupt | ||
| 620 | mov bx,RCODEA_GSEL ; Y: check local flag | ||
| 621 | mov ds,bx ; DS -> R_CODE seg | ||
| 622 | ASSUME DS:R_CODE | ||
| 623 | cmp [MB_Flag],0 ; Q: do we see this move block ? | ||
| 624 | je NotInt15 ; N: process as normal int | ||
| 625 | ; Y: emulate move block | ||
| 626 | ; set up VM1_GSEL to point to ES:0 from | ||
| 627 | ; Virtual Mode | ||
| 628 | ;NOTE: DS -> R_CODE | ||
| 629 | inc si | ||
| 630 | mov [bp.VTFOE+VMTF_EIP], si ; point beyond int6 instr | ||
| 631 | mov bx,GDTD_GSEL | ||
| 632 | mov es,bx ; ES pts to GDT | ||
| 633 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = ES seg addr | ||
| 634 | shl bx,4 ; BX = low 16 bits of ES addr | ||
| 635 | mov es:[VM1_GSEL+2],bx ; set low 16 bits of ES base addr | ||
| 636 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = ES seg addr again | ||
| 637 | shr bx,4 ; BH = high 8 bits of ES addr | ||
| 638 | mov es:[VM1_GSEL+4],bh ; place in descriptor | ||
| 639 | |||
| 640 | mov bx,VM1_GSEL | ||
| 641 | mov es,bx ; ES pts to VM ES area | ||
| 642 | |||
| 643 | mov bx,sp ; SS:BX -> GP Fault stack frame | ||
| 644 | mov si,SS:[bx.GPF_ESI] ; ES:SI pts to caller's gdt | ||
| 645 | call move_block ; move block function | ||
| 646 | mov ds:[MB_Flag],0 ; turn off flag !! | ||
| 647 | |||
| 648 | ASSUME DS:DGROUP ; done with R_CODE | ||
| 649 | |||
| 650 | jmp short EmSkipLockExit ; exit, but skip table lock. | ||
| 651 | ; move block MAY unlock tables. | ||
| 652 | ; | ||
| 653 | ; Adjust client's SP to make room for building his IRET frame | ||
| 654 | ; | ||
| 655 | NotInt15: | ||
| 656 | sub word ptr [bp.VTFOE+VMTF_ESP],6 ; adjust client's SP | ||
| 657 | mov bx,VM1_GSEL | ||
| 658 | mov ds,bx ; DS = VM stack segment | ||
| 659 | mov si,[bp.VTFOE+VMTF_ESP] ; DS:SI -> client's IRET stack frame | ||
| 660 | ; | ||
| 661 | ; Move low 16 bits of Flags, CS, and EIP from IRET frame to client stack frame | ||
| 662 | ; | ||
| 663 | mov bx,[bp.VTFOE+VMTF_EFLAGS] ; low word of EFLAGS | ||
| 664 | ; | ||
| 665 | ; *** Clear IF bit on flags for reflect, but leave it unchanged for the | ||
| 666 | ; flags on the IRET stack we build on the client's stack | ||
| 667 | ; *** Also clear the Trace Flag -> because all software INTs clear the trace | ||
| 668 | ; flag. | ||
| 669 | ; | ||
| 670 | and [bp.VTFOE+VMTF_EFLAGS],not 300h | ||
| 671 | |||
| 672 | mov ds:[si.4],bx ; to client's flags | ||
| 673 | mov bx,[bp.VTFOE+VMTF_CS] ; | ||
| 674 | mov ds:[si.2],bx ; to client's CS | ||
| 675 | mov bx,[bp.VTFOE+VMTF_EIP] ; low word of EIP | ||
| 676 | add bx,2 ; set IP past the instruction we emulate | ||
| 677 | mov ds:[si.0],bx ; to client's IP | ||
| 678 | ; | ||
| 679 | ; Replace low 16 bits of IRET frame CS:EIP with vector from real mode IDT | ||
| 680 | ; | ||
| 681 | mov si,VM2_GSEL | ||
| 682 | mov ds,si ; DS -> Client's code segment | ||
| 683 | mov bl,ds:[bx-1] ; get INTerrupt number | ||
| 684 | xor bh,bh ; BX has INT number | ||
| 685 | shl bx,2 ; BX = BX * 4 (vector table index) | ||
| 686 | mov si,RM_IDT_GSEL ; get real mode IDT alias | ||
| 687 | mov ds,si ; DS -> Real Mode IDT | ||
| 688 | mov si,ds:[bx] ; | ||
| 689 | mov [bp.VTFOE+VMTF_EIP],si ; move the IP | ||
| 690 | mov si,ds:[bx+2] ; | ||
| 691 | mov [bp.VTFOE+VMTF_CS],si ; move the CS | ||
| 692 | ; | ||
| 693 | ; 32-bit IRET back to client | ||
| 694 | ; | ||
| 695 | EmExit: | ||
| 696 | HwTabLock ; enable the high ram hw protection | ||
| 697 | EmSkipLockExit: ; as the label implies... | ||
| 698 | POP_ESI ; restore local regs | ||
| 699 | POP_EBX | ||
| 700 | POP_EBP | ||
| 701 | add sp,4 ; throw away error code | ||
| 702 | OP32_IRET ; *** RETURN *** to client | ||
| 703 | EmINTnn endp | ||
| 704 | |||
| 705 | page | ||
| 706 | ;****************************************************************************** | ||
| 707 | ; EmINT3 - emulate the 'breakpoint' interrupt instruction | ||
| 708 | ; | ||
| 709 | ; ENTRY: 386 Protected Mode | ||
| 710 | ; EBP,EBX,ESI pushed on stack | ||
| 711 | ; VM1_GSEL = VM client's stack segment | ||
| 712 | ; VM2_GSEL = VM client's code segment | ||
| 713 | ; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL) | ||
| 714 | ; EXIT: via IRET to VM client | ||
| 715 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 716 | ; USED: (none) | ||
| 717 | ; STACK: | ||
| 718 | ; | ||
| 719 | ; to do: implement the handler | ||
| 720 | ;------------------------------------------------------------------------------ | ||
| 721 | EmINT3 proc near | ||
| 722 | mov ES:[RefNum], 03h ; Vector to VM int 3 handler | ||
| 723 | RefIntN: | ||
| 724 | inc si ; fault, not a trap | ||
| 725 | mov [bp.VTFOE+VMTF_EIP], si ; point beyond int3 | ||
| 726 | jmp RefToRom ; and let the VM OS handle it | ||
| 727 | EmINT3 endp | ||
| 728 | |||
| 729 | ;****************************************************************************** | ||
| 730 | ; EmINTO - emulate overflow interrupt | ||
| 731 | ; | ||
| 732 | ; ENTRY: 386 Protected Mode | ||
| 733 | ; EBP,EBX,ESI pushed on stack | ||
| 734 | ; VM1_GSEL = VM client's stack segment | ||
| 735 | ; VM2_GSEL = VM client's code segment | ||
| 736 | ; DS:SI -> faulting opcode = CD nn (DS = VM2_GSEL) | ||
| 737 | ; EXIT: via IRET to VM client | ||
| 738 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 739 | ; USED: (none) | ||
| 740 | ; STACK: | ||
| 741 | ;------------------------------------------------------------------------------ | ||
| 742 | EmINTO proc near | ||
| 743 | mov ES:[RefNum], 04h ; Vector to VM int 3 handler | ||
| 744 | jmp short RefIntN | ||
| 745 | EmINTO endp | ||
| 746 | |||
| 747 | page | ||
| 748 | ;****************************************************************************** | ||
| 749 | ; EmINB - emulate the IN byte instruction | ||
| 750 | ; | ||
| 751 | ; ENTRY: 386 Protected Mode | ||
| 752 | ; EBP,EBX,ESI pushed on stack | ||
| 753 | ; VM1_GSEL = VM client's stack segment | ||
| 754 | ; VM2_GSEL = VM client's code segment | ||
| 755 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 756 | ; EXIT: via IRET to VM client | ||
| 757 | ; USED: | ||
| 758 | ; STACK: n/a | ||
| 759 | ;------------------------------------------------------------------------------ | ||
| 760 | EmINB proc near | ||
| 761 | inc si | ||
| 762 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 763 | push bx | ||
| 764 | xor bx,bx ; IN instruction | ||
| 765 | call IO_Trap ; Q: Emulated ? | ||
| 766 | jnc EINB_Exit ; Y: exit | ||
| 767 | in al,dx ; N:do the INput | ||
| 768 | EINB_Exit: | ||
| 769 | pop bx | ||
| 770 | jmp EmExit ; *** RETURN *** to VM client | ||
| 771 | EmINB endp | ||
| 772 | |||
| 773 | page | ||
| 774 | ;****************************************************************************** | ||
| 775 | ; EmINW - emulate IN word | ||
| 776 | ; | ||
| 777 | ; This routine emulates the IN word instruction | ||
| 778 | ; | ||
| 779 | ; ENTRY 386 PROTECTED MODE | ||
| 780 | ; see common description at top | ||
| 781 | ; | ||
| 782 | ; EXIT IRET back to VM program | ||
| 783 | ;------------------------------------------------------------------------------ | ||
| 784 | EmINW proc near | ||
| 785 | inc si | ||
| 786 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 787 | push bx | ||
| 788 | xor bx,bx ; IN instruction | ||
| 789 | call IO_Trap ; Q: Emulated ? | ||
| 790 | cbw ; AX= returned value | ||
| 791 | jnc EINW_Exit ; Y: exit | ||
| 792 | in ax,dx ; N:do the word INput | ||
| 793 | EINW_Exit: ; | ||
| 794 | pop bx ; | ||
| 795 | jmp EmExit ; *** RETURN *** to VM client | ||
| 796 | EmINW endp | ||
| 797 | |||
| 798 | page | ||
| 799 | ;****************************************************************************** | ||
| 800 | ; EmINBimm - emulate IN word immediate | ||
| 801 | ; | ||
| 802 | ; This routine emulates the IN word immediate instruction | ||
| 803 | ; | ||
| 804 | ; ENTRY 386 PROTECTED MODE | ||
| 805 | ; see common description at top | ||
| 806 | ; | ||
| 807 | ; EXIT IRET back to VM program | ||
| 808 | ;------------------------------------------------------------------------------ | ||
| 809 | EmINBimm proc near | ||
| 810 | push bx | ||
| 811 | push dx | ||
| 812 | mov dl,ds:[si+1] ; get port number | ||
| 813 | xor dh,dh ; DX has INT number | ||
| 814 | add si, 2 | ||
| 815 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 816 | xor bx,bx ; IN instruction | ||
| 817 | call IO_Trap ; Q: Emulated ? | ||
| 818 | jnc EINBi_Exit ; Y: exit | ||
| 819 | in al,dx ; N:do the INput | ||
| 820 | EINBi_exit: | ||
| 821 | pop dx | ||
| 822 | pop bx | ||
| 823 | jmp EmExit ; *** RETURN *** to VM client | ||
| 824 | EmINBimm endp | ||
| 825 | |||
| 826 | page | ||
| 827 | ;****************************************************************************** | ||
| 828 | ;*** EmINWimm - emulate IN word immediate | ||
| 829 | ; | ||
| 830 | ; This routine emulates the IN word immediate instruction | ||
| 831 | ; | ||
| 832 | ; ENTRY 386 PROTECTED MODE | ||
| 833 | ; see common description at top | ||
| 834 | ; | ||
| 835 | ; EXIT IRET back to VM program | ||
| 836 | ;------------------------------------------------------------------------------ | ||
| 837 | EmINWimm proc near | ||
| 838 | push bx | ||
| 839 | push dx | ||
| 840 | mov dl,ds:[si+1] ; get port number | ||
| 841 | xor dh,dh ; DX has INT number | ||
| 842 | add si, 2 | ||
| 843 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 844 | xor bx,bx ; IN instruction | ||
| 845 | call IO_Trap ; Q: Emulated ? | ||
| 846 | cbw ; AX = returned value | ||
| 847 | jnc EINWi_Exit ; Y: exit | ||
| 848 | in ax,dx ; N:do the word INput | ||
| 849 | EINWi_Exit: | ||
| 850 | pop dx | ||
| 851 | pop bx | ||
| 852 | jmp EmExit ; *** RETURN *** to VM client | ||
| 853 | EmINWimm endp | ||
| 854 | |||
| 855 | page | ||
| 856 | ;****************************************************************************** | ||
| 857 | ;*** EmOUTB - emulate OUT byte | ||
| 858 | ; | ||
| 859 | ; This routine emulates the OUT byte instruction | ||
| 860 | ; | ||
| 861 | ; ENTRY 386 PROTECTED MODE | ||
| 862 | ; see common description at top | ||
| 863 | ; | ||
| 864 | ; EXIT IRET back to VM program | ||
| 865 | ; | ||
| 866 | EmOUTB proc near | ||
| 867 | inc si | ||
| 868 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 869 | push bx | ||
| 870 | push dx | ||
| 871 | mov bx,1 ; OUT instruction | ||
| 872 | call IO_Trap ; Q: Emulated ? | ||
| 873 | jnc EOUTB_Exit ; Y:exit | ||
| 874 | EOUTB_em: | ||
| 875 | out dx,al ; N:do the byte OUTput | ||
| 876 | EOUTB_Exit: | ||
| 877 | pop dx | ||
| 878 | pop bx | ||
| 879 | jmp EmExit ; *** RETURN *** to VM client | ||
| 880 | EmOUTB endp | ||
| 881 | |||
| 882 | page | ||
| 883 | ;****************************************************************************** | ||
| 884 | ;*** EmOUTW - emulate OUT word | ||
| 885 | ; | ||
| 886 | ; This routine emulates the OUT word instruction | ||
| 887 | ; | ||
| 888 | ; ENTRY 386 PROTECTED MODE | ||
| 889 | ; see common description at top | ||
| 890 | ; | ||
| 891 | ; EXIT IRET back to VM program | ||
| 892 | ; | ||
| 893 | EmOUTW proc near | ||
| 894 | inc si | ||
| 895 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 896 | push bx | ||
| 897 | mov bx,1 ; OUT instruction | ||
| 898 | call IO_Trap ; Q: Emulated ? | ||
| 899 | jnc EOUTW_Exit ; Y: exit | ||
| 900 | ; N: | ||
| 901 | out dx,ax ; do the word OUTput | ||
| 902 | EOUTW_Exit: | ||
| 903 | pop bx | ||
| 904 | jmp EmExit ; *** RETURN *** to VM client | ||
| 905 | EmOUTW endp | ||
| 906 | |||
| 907 | page | ||
| 908 | ;****************************************************************************** | ||
| 909 | ;*** EmOUTBimm - emulate OUT byte immediate | ||
| 910 | ; | ||
| 911 | ; This routine emulates the OUT byte immediate | ||
| 912 | ; | ||
| 913 | ; ENTRY 386 PROTECTED MODE | ||
| 914 | ; see common description at top | ||
| 915 | ; | ||
| 916 | ; EXIT IRET back to VM program | ||
| 917 | ; | ||
| 918 | EmOUTBimm proc near | ||
| 919 | push bx | ||
| 920 | push dx | ||
| 921 | mov dl,ds:[si+1] ; get port number | ||
| 922 | xor dh,dh ; DX has INT number | ||
| 923 | add si, 2 | ||
| 924 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 925 | mov bx,1 ; OUT instruction | ||
| 926 | call IO_Trap ; Q: Emulated ? | ||
| 927 | jnc EOUTBi_Exit ; Y:exit | ||
| 928 | EOUTBi_em: | ||
| 929 | out dx,al ; N:do the byte OUTput | ||
| 930 | EOUTBi_Exit: | ||
| 931 | pop dx | ||
| 932 | pop bx | ||
| 933 | jmp EmExit ; *** RETURN *** to VM client | ||
| 934 | EmOUTBimm endp | ||
| 935 | |||
| 936 | page | ||
| 937 | ;****************************************************************************** | ||
| 938 | ;*** EmOUTWimm - emulate OUT word immediate | ||
| 939 | ; | ||
| 940 | ; This routine emulates the OUT word immediate instruction | ||
| 941 | ; | ||
| 942 | ; ENTRY 386 PROTECTED MODE | ||
| 943 | ; see common description at top | ||
| 944 | ; | ||
| 945 | ; EXIT IRET back to VM program | ||
| 946 | ; | ||
| 947 | EmOUTWimm proc near | ||
| 948 | push bx | ||
| 949 | push dx | ||
| 950 | mov dl,ds:[si+1] ; get port number | ||
| 951 | xor dh,dh ; DX has INT number | ||
| 952 | add si, 2 | ||
| 953 | mov [bp.VTFOE+VMTF_EIP],si ; set IP past the instruction we emulate | ||
| 954 | mov bx,1 ; OUT instruction | ||
| 955 | call IO_Trap ; Q: Emulated ? | ||
| 956 | jnc EOUTWi_Exit ; Y: exit | ||
| 957 | out dx,ax ; N:do the word OUTput | ||
| 958 | EOUTWi_Exit: | ||
| 959 | pop dx | ||
| 960 | pop bx | ||
| 961 | jmp EmExit ; *** RETURN *** to VM client | ||
| 962 | EmOUTWimm endp | ||
| 963 | page | ||
| 964 | ;****************************************************************************** | ||
| 965 | ;*** EmHALT - Emulate HALT command | ||
| 966 | ; | ||
| 967 | ; This routine is entered if a faulting instruction | ||
| 968 | ; is a HALT command | ||
| 969 | ; | ||
| 970 | ; ENTRY 386 PROTECTED MODE | ||
| 971 | ; see common description at top | ||
| 972 | ; | ||
| 973 | ; EXIT return to VM client unless client IF=0 then | ||
| 974 | ; HLT is executed with IF=0 | ||
| 975 | ; | ||
| 976 | EmHALT proc near | ||
| 977 | ; Q: client's IF bit is 0? | ||
| 978 | test word ptr [bp.VTFOE+VMTF_EFLAGS], IF_FLAG | ||
| 979 | jz EmDoHlt ; Y: execute HLT if IF=0 | ||
| 980 | inc si ; inc VM CS:IP past command | ||
| 981 | mov [bp.VTFOE+VMTF_EIP], si ; we emulate | ||
| 982 | ; A halt on an INTEL architecture machine is just waiting for an interrupt | ||
| 983 | ; We'll pretend an interrupt occurs after a short wait | ||
| 984 | push cx | ||
| 985 | mov cx,4000h | ||
| 986 | loop $ ; Wait awhile | ||
| 987 | pop cx | ||
| 988 | jmp EmExit ; then leave | ||
| 989 | emDoHlt: | ||
| 990 | cli | ||
| 991 | hlt ; Halt till NMI | ||
| 992 | jmp EmExit | ||
| 993 | |||
| 994 | EmHALT endp | ||
| 995 | |||
| 996 | page | ||
| 997 | ;****************************************************************************** | ||
| 998 | ;*** EmLoadal2 - Emulate 286 Loadall command | ||
| 999 | ; | ||
| 1000 | ; This routine is entered if a faulting instruction | ||
| 1001 | ; is a Loadall 286 command | ||
| 1002 | ; | ||
| 1003 | ; ENTRY 386 PROTECTED MODE | ||
| 1004 | ; see common description at top | ||
| 1005 | ; | ||
| 1006 | ; EXIT return to VM client | ||
| 1007 | ; | ||
| 1008 | EmLoadal2 proc near | ||
| 1009 | |||
| 1010 | test ES:[PrefixFlag],P0F_FLAG ; Q:Do we have the right prefix? | ||
| 1011 | jz Not_Loadall | ||
| 1012 | jmp EM286ll ; Y: emulate 286 loadall | ||
| 1013 | |||
| 1014 | Not_Loadall: | ||
| 1015 | jmp BadVmTrap ; N: Vector to VM illegal opcode | ||
| 1016 | |||
| 1017 | EmLoadal2 endp | ||
| 1018 | |||
| 1019 | ;****************************************************************************** | ||
| 1020 | ;*** EmLoadal3 - Emulate 386 Loadall command | ||
| 1021 | ; | ||
| 1022 | ; This routine is entered if a faulting instruction | ||
| 1023 | ; is a Loadall 386 command | ||
| 1024 | ; | ||
| 1025 | ; ENTRY 386 PROTECTED MODE | ||
| 1026 | ; see common description at top | ||
| 1027 | ; | ||
| 1028 | ; EXIT return to VM client | ||
| 1029 | ; | ||
| 1030 | EmLoadal3 proc near | ||
| 1031 | |||
| 1032 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1033 | jz Not_Loadall | ||
| 1034 | jmp EM386ll ; Y: emulate 386 loadall | ||
| 1035 | |||
| 1036 | EmLoadal3 endp | ||
| 1037 | |||
| 1038 | ;****************************************************************************** | ||
| 1039 | ; EmCLTS - emulate the CLTS instruction | ||
| 1040 | ; | ||
| 1041 | ; ENTRY: 386 Protected Mode | ||
| 1042 | ; EBP,EBX,ESI pushed on stack | ||
| 1043 | ; VM1_GSEL = VM client's stack segment | ||
| 1044 | ; VM2_GSEL = VM client's code segment | ||
| 1045 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 1046 | ; EXIT: via IRET to VM client | ||
| 1047 | ; USED: | ||
| 1048 | ; STACK: n/a | ||
| 1049 | ;------------------------------------------------------------------------------ | ||
| 1050 | EmCLTS proc near | ||
| 1051 | |||
| 1052 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1053 | jz Not_CLTS | ||
| 1054 | clts ; go ahead and CLTS | ||
| 1055 | inc si ; inc VM CS:IP past command | ||
| 1056 | mov [bp.VTFOE+VMTF_EIP], si ; we emulate | ||
| 1057 | jmp EmExit ; and leave | ||
| 1058 | |||
| 1059 | Not_CLTS: | ||
| 1060 | jmp BadVmTrap | ||
| 1061 | |||
| 1062 | EmCLTS endp | ||
| 1063 | |||
| 1064 | ;****************************************************************************** | ||
| 1065 | ; EmProtIns - emulate the protection control instructions | ||
| 1066 | ; Currently this throws LIDT and LGDT to the error handler and only emulates | ||
| 1067 | ; LMSW | ||
| 1068 | ; NOTE: The Stack configuration is critical!!! If it is changed, the | ||
| 1069 | ; offsets to the register images must be updated accordingly. | ||
| 1070 | ; | ||
| 1071 | ; | ||
| 1072 | ; ENTRY: 386 Protected Mode | ||
| 1073 | ; EBP,EBX,ESI pushed on stack | ||
| 1074 | ; VM1_GSEL = VM client's stack segment | ||
| 1075 | ; VM2_GSEL = VM client's code segment | ||
| 1076 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 1077 | ; EXIT: via IRET to VM client | ||
| 1078 | ; bp.VTFOE+VMTF_EIP points beyond offender to next client instruction | ||
| 1079 | ; VM2_GSEL, DS, and SI may be modified at exit, this should not be a | ||
| 1080 | ; problem for the IRET | ||
| 1081 | ; USED: | ||
| 1082 | ; STACK: n/a | ||
| 1083 | ;------------------------------------------------------------------------------ | ||
| 1084 | EmProtIns proc near | ||
| 1085 | |||
| 1086 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1087 | jnz EmPI1 | ||
| 1088 | jmp Not_ProtIns1 | ||
| 1089 | EmPI1: | ||
| 1090 | push dx | ||
| 1091 | push ax | ||
| 1092 | push es | ||
| 1093 | mov dx, ES:[PrefixFlag] | ||
| 1094 | mov bx,VDMCA_GSEL ; Load CODE (writeable) alias | ||
| 1095 | mov es, bx | ||
| 1096 | assume es:_TEXT | ||
| 1097 | inc si ; set si past the opcode | ||
| 1098 | mov bl,[si] ; BL = modR/M | ||
| 1099 | mov bh, bl ; BH = modR/M | ||
| 1100 | and bl, 38h | ||
| 1101 | cmp bl, 30h | ||
| 1102 | je EmLMSW ; Emulate LMSW | ||
| 1103 | cmp bl, 18h | ||
| 1104 | jne LGDTerr ; VM guy not allowed to LGDT | ||
| 1105 | mov bx, ErrLIDT | ||
| 1106 | jmp ExitPIer ; VM guy not allowed to LIDT | ||
| 1107 | LGDTerr: | ||
| 1108 | mov bx, ErrLGDT | ||
| 1109 | jmp ExitPIer | ||
| 1110 | EmLMSW: | ||
| 1111 | inc si ; set SI past the modR/M | ||
| 1112 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1113 | mov bl, bh ; BL = modR/M | ||
| 1114 | cmp bl, 0C0h ; is MSW being loaded from a register? | ||
| 1115 | jb MoveData ; N: do a move from the VM's memory | ||
| 1116 | jmp MoveReg ; Y: go do a register move | ||
| 1117 | |||
| 1118 | MoveData: | ||
| 1119 | ; Because of all the possible addressing modes this is pretty nasty. Like | ||
| 1120 | ; MoveReg, it is complicated by the requirement to not clear the PE bit. | ||
| 1121 | ; The general approach is to find the client's data value, put it in AX, | ||
| 1122 | ; set the PE bit in AX, then load the MSW from AX. To keep from having | ||
| 1123 | ; to know about all the modR/M combinations, we yank the client's possible | ||
| 1124 | ; offset from his code, and put his slightly modified modR/M byte in our | ||
| 1125 | ; home-made MOV AX, MemData instruction. | ||
| 1126 | |||
| 1127 | ; If there is a data offset, yank it from the VM instruction and put it | ||
| 1128 | ; in our instruction. | ||
| 1129 | |||
| 1130 | and bl, 0C7h ; Force AX to be the MOV destination | ||
| 1131 | mov byte ptr es:[LMSWmod],bl | ||
| 1132 | mov ax, 09090h | ||
| 1133 | mov word ptr es:[LMSWoff],ax ; initialize offset to NOPS | ||
| 1134 | cmp bl, 06h ; special case for DS:d16 | ||
| 1135 | je load16off | ||
| 1136 | and bl, 0C0h | ||
| 1137 | cmp bl, 040h | ||
| 1138 | je load8off | ||
| 1139 | cmp bl, 080h | ||
| 1140 | jne BldDesc ; No data offset, so go build desc | ||
| 1141 | Load16off: | ||
| 1142 | mov ax,[si] ; AX = 16 bit offset | ||
| 1143 | mov word ptr es:[LMSWoff],ax | ||
| 1144 | add si, 2 | ||
| 1145 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1146 | jmp short BldDesc | ||
| 1147 | Load8off: | ||
| 1148 | mov al,[si] ; AL = 8 bit offset | ||
| 1149 | mov byte ptr es:[LMSWoff],al | ||
| 1150 | inc si | ||
| 1151 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1152 | |||
| 1153 | BldDesc: | ||
| 1154 | ; Build a descriptor to the client's data segment | ||
| 1155 | |||
| 1156 | mov bl, bh | ||
| 1157 | mov ax, [bp.VTFOE+VMTF_DS] ; Assume DS is the data segment | ||
| 1158 | |||
| 1159 | ; Check for segment override | ||
| 1160 | and dx, 00FCh ; strip all but segment overrides | ||
| 1161 | cmp dx, CS_FLAG | ||
| 1162 | jl GetmodBase ; no override, check base | ||
| 1163 | je CS_data | ||
| 1164 | cmp dx, ES_FLAG | ||
| 1165 | je ES_data | ||
| 1166 | jl GetSel ; ds is override | ||
| 1167 | cmp dx, FS_FLAG | ||
| 1168 | jl SS_data | ||
| 1169 | je FS_data | ||
| 1170 | GS_data: | ||
| 1171 | mov ax, [bp.VTFOE+VMTF_GS] ; GS is the data segment | ||
| 1172 | jmp short GetSel | ||
| 1173 | FS_data: | ||
| 1174 | mov ax, [bp.VTFOE+VMTF_FS] ; FS is the data segment | ||
| 1175 | jmp short GetSel | ||
| 1176 | SS_data: | ||
| 1177 | mov ax, VM1_GSEL | ||
| 1178 | mov ds, ax | ||
| 1179 | jmp short RestoreRegs | ||
| 1180 | CS_data: | ||
| 1181 | mov ax, VM2_GSEL | ||
| 1182 | mov ds, ax | ||
| 1183 | jmp short RestoreRegs | ||
| 1184 | ES_data: | ||
| 1185 | mov ax, [bp.VTFOE+VMTF_ES] ; ES is the data segment | ||
| 1186 | jmp short GetSel | ||
| 1187 | |||
| 1188 | GetmodBase: | ||
| 1189 | ; We have no Segment override, so we need to look at the modR/M byte to | ||
| 1190 | ; see whether or not the data index/offset is based on DS (assumed) or SS | ||
| 1191 | and bl, 0C7h ; clear instruction bits | ||
| 1192 | cmp bl, 46h | ||
| 1193 | je SS_Data ; EA = SS:[BP+d8] | ||
| 1194 | and bl, 7 | ||
| 1195 | cmp bl, 2 | ||
| 1196 | je SS_Data ; EA = SS:[BP+SI+?] | ||
| 1197 | cmp bl, 3 | ||
| 1198 | je SS_Data ; EA = SS:[BP+DI+?] | ||
| 1199 | |||
| 1200 | GetSel: | ||
| 1201 | ; Build a selector (VM2_GSEL) to client's data. VM2_GSEL is already set | ||
| 1202 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1203 | ; The Descriptor base VM segment value is in AX | ||
| 1204 | push es | ||
| 1205 | push bx | ||
| 1206 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 1207 | mov es,bx ; DS -> GDT | ||
| 1208 | mov bx, ax ; copy the VM data segment value | ||
| 1209 | shl ax,4 ; BX = low 16 bits of base | ||
| 1210 | mov es:[VM2_GSEL+2],ax ; place in descriptor | ||
| 1211 | shr bx,4 ; BH = high 8 bits of base | ||
| 1212 | mov es:[VM2_GSEL+4],bh ; place in descriptor | ||
| 1213 | mov ax, VM2_GSEL | ||
| 1214 | mov ds, ax | ||
| 1215 | pop bx | ||
| 1216 | pop es | ||
| 1217 | |||
| 1218 | RestoreRegs: | ||
| 1219 | ; Since BX, SI, DI, and BP can all be used to form an effective address we | ||
| 1220 | ; blindly restore BX, SI, and BP from the stack so that we don't | ||
| 1221 | ; have to know what the instruction is using for its effective address. | ||
| 1222 | ; DI does not need to be restored, because it should still be the client's | ||
| 1223 | |||
| 1224 | push bp | ||
| 1225 | mov bp, sp | ||
| 1226 | |||
| 1227 | ; Now the Stack had better look like PROT_INS_FRAME. (vm386.inc) | ||
| 1228 | mov si, [bp.PIF_ESI] | ||
| 1229 | mov bx, [bp.PIF_EBX] | ||
| 1230 | mov bp, [bp.PIF_EBP] | ||
| 1231 | |||
| 1232 | ; Move the VM data operand to AX | ||
| 1233 | db 3Eh ; ds overide (for bp & di) | ||
| 1234 | db 8Bh ; MOV opcode | ||
| 1235 | LMSWmod db 00h ; modR/M | ||
| 1236 | LMSWoff db 90h, 90h ; possible offset (NOPS otherwise) | ||
| 1237 | |||
| 1238 | jmp ExLMSW ; Finally... go do the LMSW | ||
| 1239 | |||
| 1240 | MoveReg: | ||
| 1241 | ; Here we have a LMSW from one of the general registers. This is pretty | ||
| 1242 | ; ugly because many of the possible registers the client might have used | ||
| 1243 | ; are currently saved on the stack. It is also complicated by the | ||
| 1244 | ; requirement to not clear the PE bit. The general approach is to find | ||
| 1245 | ; the client's register value/image, put it in AX, set the PE bit in AX, | ||
| 1246 | ; then load the MSW from AX. To keep from having to know all the modR/M | ||
| 1247 | ; combinations, we again use a slightly modified client's modR/M byte in | ||
| 1248 | ; our home-made MOV AX, RegData instruction. | ||
| 1249 | |||
| 1250 | push bp | ||
| 1251 | mov bp, sp | ||
| 1252 | |||
| 1253 | ; Now the Stack had better look like PROT_INS_FRAME. (vm386.inc) | ||
| 1254 | |||
| 1255 | and bh, 07h ; If Src is AX, it hasn't been changed | ||
| 1256 | jz ExLMSW ; so just go do the the LMSW | ||
| 1257 | CkSrcBX: ; otherwise, find it and move it to AX | ||
| 1258 | cmp bh, 3 | ||
| 1259 | jne CkSrcBP | ||
| 1260 | mov ax, [bp.PIF_EBX] ; src was BX, get from stack | ||
| 1261 | jmp short ExLMSW | ||
| 1262 | CkSrcBP: | ||
| 1263 | cmp bh, 5 | ||
| 1264 | jne CkSrcSI | ||
| 1265 | mov ax, [bp.PIF_EBP] ; src was BP, get from stack | ||
| 1266 | jmp short ExLMSW | ||
| 1267 | CkSrcSI: | ||
| 1268 | cmp bh, 6 | ||
| 1269 | jne CkSrcDX | ||
| 1270 | mov ax, [bp.PIF_ESI] ; src was SI, get from stack | ||
| 1271 | jmp short ExLMSW | ||
| 1272 | CkSrcDX: | ||
| 1273 | cmp bh, 2 | ||
| 1274 | jne CkSrcSP | ||
| 1275 | mov ax, [bp.PIF_DX] ; src was DX, get from stack | ||
| 1276 | jmp short ExLMSW | ||
| 1277 | CkSrcSP: | ||
| 1278 | cmp bh, 4 | ||
| 1279 | jne GetReg | ||
| 1280 | mov ax, [bp.PIF_VMESP] ; src was SP, get from stack | ||
| 1281 | jmp short ExLMSW | ||
| 1282 | GetReg: | ||
| 1283 | or bh, 0C0h ; set register to register move bits | ||
| 1284 | mov es:[Lmod], bh ; setup move from client's src register | ||
| 1285 | jmp short GetRn ; clear prefetch so that bh gets there | ||
| 1286 | GetRn: | ||
| 1287 | ; Execute MOV AX, Rn | ||
| 1288 | db 08Bh | ||
| 1289 | Lmod db 0C0h | ||
| 1290 | |||
| 1291 | ; Finally Execute the LMSW | ||
| 1292 | ExLMSW: | ||
| 1293 | |||
| 1294 | ; At this point we could check for the PE bit and notify the user that | ||
| 1295 | ; he must switch to real mode... but because an old app might do a SMSW, | ||
| 1296 | ; which copies the PE bit (?!!), then set a bit in that image and do a LMSW, | ||
| 1297 | ; (not caring about the PE bit), we just let it go... under the assumption | ||
| 1298 | ; that if he really were trying to enter Protected mode, he would have | ||
| 1299 | ; failed trying to LIDT and LGDT. | ||
| 1300 | |||
| 1301 | ; test ax, 0001h ; Is client trying to set PE bit | ||
| 1302 | ; jnz ExitPIer ; Y: jump to error | ||
| 1303 | or ax, 0001h ; N: we want to stay in Prot mode | ||
| 1304 | LMSW ax ; So we must set it (use BTS above) | ||
| 1305 | |||
| 1306 | pop bp | ||
| 1307 | pop es | ||
| 1308 | assume es:DGROUP | ||
| 1309 | pop ax | ||
| 1310 | pop dx | ||
| 1311 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1312 | |||
| 1313 | ExitPIer: | ||
| 1314 | pop es | ||
| 1315 | assume es:DGROUP | ||
| 1316 | mov ax, PrivErr ; privileged error | ||
| 1317 | call ErrHndlr ; If the user want's to continue | ||
| 1318 | pop ax | ||
| 1319 | pop dx | ||
| 1320 | jmp JumpReal ; we return and go unwind the stack | ||
| 1321 | Not_ProtIns1: | ||
| 1322 | jmp BadVmTrap | ||
| 1323 | |||
| 1324 | EmProtIns endp | ||
| 1325 | |||
| 1326 | ;****************************************************************************** | ||
| 1327 | ; EmMovCDTR - emulate the - MOV Rn, C/D/TRn & MOV C/D/TRn, Rn - instructions | ||
| 1328 | ; This is done by copying the MOV instruction from the VM to our | ||
| 1329 | ; code and then executing it. If CR0 is being stored, the PE | ||
| 1330 | ; bit is masked clear before completing the instruction. Execution speed | ||
| 1331 | ; should not be critical for these instructions, so I have lumped them | ||
| 1332 | ; all together to save memory that can be better used for more time | ||
| 1333 | ; critical emulations. | ||
| 1334 | ; NOTE: The Stack configuration is critical!!! If it is changed, the | ||
| 1335 | ; offsets to the register images must be updated accordingly. | ||
| 1336 | ; | ||
| 1337 | ; Also NOTE: The TR register opcodes have been removed from the legal 0F | ||
| 1338 | ; prefix list, (P0F_OpTab(x)), and the EmMovCDTR address removed from their | ||
| 1339 | ; opcode table ,(OpTable), vectors, so that they don't come here anymore. | ||
| 1340 | ; | ||
| 1341 | ; ENTRY: 386 Protected Mode | ||
| 1342 | ; EBP,EBX,ESI pushed on stack | ||
| 1343 | ; VM1_GSEL = VM client's stack segment | ||
| 1344 | ; VM2_GSEL = VM client's code segment | ||
| 1345 | ; DS:SI -> faulting opcode = nn (DS = VM2_GSEL) | ||
| 1346 | ; EXIT: via IRET to VM client | ||
| 1347 | ; bp.VTFOE+VMTF_EIP points beyond offender to next client instruction | ||
| 1348 | ; USED: | ||
| 1349 | ; STACK: n/a | ||
| 1350 | ;------------------------------------------------------------------------------ | ||
| 1351 | EmMovCDTR proc near | ||
| 1352 | |||
| 1353 | test ES:[PrefixFlag],P0F_FLAG | ||
| 1354 | jnz MovCDTR1 | ||
| 1355 | jmp Not_MovCDTR ; Didn't come from a 0F prefix | ||
| 1356 | MovCDTR1: | ||
| 1357 | PUSH_EAX | ||
| 1358 | push es | ||
| 1359 | mov bx,VDMCA_GSEL ; Load CODE (writeable) alias | ||
| 1360 | mov es, bx | ||
| 1361 | assume es:_TEXT | ||
| 1362 | mov bl,[si] ; BL = opcode | ||
| 1363 | mov es:[CDTRopc], bl | ||
| 1364 | inc si ; set SI past the opcode | ||
| 1365 | mov bl,[si] ; BL = modR/M | ||
| 1366 | mov bh, bl ; Copy modR/M | ||
| 1367 | and bl, 0F8h ; For control, we reroute move thru AX | ||
| 1368 | mov es:[CDTRmod], bl | ||
| 1369 | inc si ; set SI past the modR/M | ||
| 1370 | mov [bp.VTFOE+VMTF_EIP],si ; VM CS:IP = DS:SI | ||
| 1371 | |||
| 1372 | push bp | ||
| 1373 | mov bp, sp | ||
| 1374 | |||
| 1375 | ; Now the Stack had better look like MOV_CDTR_FRAME. (vm386.inc) | ||
| 1376 | |||
| 1377 | mov bl, es:[CDTRopc] ; load opcode | ||
| 1378 | cmp bl, 024h ; Check TRn load/store | ||
| 1379 | jb NotTRErr ; N: continue | ||
| 1380 | mov bx, ErrMovTR ; Y: go flag error | ||
| 1381 | jmp CTRErr | ||
| 1382 | |||
| 1383 | NotTRErr: | ||
| 1384 | and bh, 7 ; strip all but src reg bits | ||
| 1385 | cmp bh, 0 | ||
| 1386 | je ExCDTR ; reg is AX, so just do move | ||
| 1387 | |||
| 1388 | cmp bl, 020h ; Check CRn store | ||
| 1389 | je ExCDTR1 ; Y: go do it | ||
| 1390 | cmp bl, 021h ; Check DRn store | ||
| 1391 | je ExCDTR1 ; Y: go do it | ||
| 1392 | |||
| 1393 | ChkSrcBX: | ||
| 1394 | cmp bh, 3 | ||
| 1395 | jne ChkSrcBP | ||
| 1396 | OP32 | ||
| 1397 | mov ax, [bp.MCF_EBX] ; mov EBX from stack | ||
| 1398 | jmp short ExCDTR | ||
| 1399 | ChkSrcBP: | ||
| 1400 | cmp bh, 5 | ||
| 1401 | jne ChkSrcSI | ||
| 1402 | OP32 | ||
| 1403 | mov ax, [bp.MCF_EBP] ; mov EBP from stack | ||
| 1404 | jmp short ExCDTR | ||
| 1405 | ChkSrcSI: | ||
| 1406 | cmp bh, 6 | ||
| 1407 | jne ChkSrcSP | ||
| 1408 | OP32 | ||
| 1409 | mov ax, [bp.MCF_ESI] ; mov ESI from stack | ||
| 1410 | jmp short ExCDTR | ||
| 1411 | ChkSrcSP: | ||
| 1412 | cmp bh, 4 | ||
| 1413 | jne GetFmReg | ||
| 1414 | OP32 | ||
| 1415 | mov ax, [bp.MCF_VMESP] ; mov ESP from stack | ||
| 1416 | jmp short ExCDTR | ||
| 1417 | GetFmReg: | ||
| 1418 | or bh, 0C0h ; set register to register move bits | ||
| 1419 | mov es:[CDTRreg], bh ; setup move from client's src register | ||
| 1420 | jmp short GetERn ; clear prefetch so that bh gets there | ||
| 1421 | GetERn: | ||
| 1422 | ; Execute MOV EAX, ERn | ||
| 1423 | OP32 | ||
| 1424 | db 08Bh | ||
| 1425 | CDTRreg db 0C0h | ||
| 1426 | |||
| 1427 | ExCDTR: | ||
| 1428 | cmp bl, 022h ; Check CRn load | ||
| 1429 | jne FltrDRL3 ; N: destination not CRn | ||
| 1430 | cmp byte ptr es:[CDTRmod], 0C0h ; Check for CR0 load | ||
| 1431 | je CR0FltrL ; Y: filter it | ||
| 1432 | mov bx, ErrMovCR | ||
| 1433 | jmp CTRErr ; N: go tell user he did a NoNo | ||
| 1434 | FltrDRL3: | ||
| 1435 | cmp byte ptr es:[CDTRmod], 0C3h ; Check for DR0-3 load | ||
| 1436 | ja FltrGDbit ; N: continue | ||
| 1437 | call MapLinear ; Y: convert address to our paging | ||
| 1438 | jmp short ExCDTR1 ; linear map, then continue | ||
| 1439 | FltrGDbit: | ||
| 1440 | cmp byte ptr es:[CDTRmod], 0C7h ; Check for DR7 load | ||
| 1441 | jne ExCDTR1 ; N: continue | ||
| 1442 | and ax, 0DFFFh ; Y: don't let client set the GD bit | ||
| 1443 | jmp short ExCDTR1 ; continue | ||
| 1444 | |||
| 1445 | ; For the reason below, we don't bug the user about setting the PE bit | ||
| 1446 | ; through LMSW. To be consistent, and because the client would die | ||
| 1447 | ; in his attmept to LGDT or Mov CR3,Reg before this, we let him go here | ||
| 1448 | ; also. | ||
| 1449 | ; LMSW Reason: | ||
| 1450 | ; At this point we could check for the PE bit and notify the user that | ||
| 1451 | ; he must switch to real mode... but because an old app might do a SMSW, | ||
| 1452 | ; which copies the PE bit (?!!), then set a bit in that image and do a LMSW, | ||
| 1453 | ; (not caring about the PE bit), we just let it go... under the assumption | ||
| 1454 | ; that if he really were trying to enter Protected mode, he would have | ||
| 1455 | ; failed trying to LIDT and LGDT. | ||
| 1456 | |||
| 1457 | CR0FltrL: | ||
| 1458 | ; OP32 | ||
| 1459 | ; test AX, 0FFFEh ; Is Client trying to set the | ||
| 1460 | ; dw 7FFFh ; PE bit or the PG bit? | ||
| 1461 | ; jnz ExitxCRer ; Y: go tell him he can't | ||
| 1462 | OP32 | ||
| 1463 | or AX, 0001h ; set PE bit | ||
| 1464 | dw 8000h ; and PG bit if they weren't | ||
| 1465 | ExCDTR1: | ||
| 1466 | ; Execute MOV CDTRn, EAX (Finally!) | ||
| 1467 | db 0Fh | ||
| 1468 | CDTRopc db 020h | ||
| 1469 | CDTRmod db 0C0h | ||
| 1470 | |||
| 1471 | ; The special register move has now been executed, but we altered it to | ||
| 1472 | ; use AX. If the move was a load, we are done. If it was a store to one of | ||
| 1473 | ; the registers on the stack, we need to stuff the register's stack image, | ||
| 1474 | ; otherwise we need to move AX to the proper register. | ||
| 1475 | |||
| 1476 | cmp bl, 022h ; Check CRn load | ||
| 1477 | je Exit_MovCDTR ; Y: we're done | ||
| 1478 | cmp bl, 023h ; Check DRn load | ||
| 1479 | je Exit_MovCDTR ; Y: we're done | ||
| 1480 | cmp bl, 021h ; Check DRn store | ||
| 1481 | je FltrDRS3 ; Y: go filter it | ||
| 1482 | jmp short NotDRS3 | ||
| 1483 | FltrDRS3: | ||
| 1484 | cmp byte ptr es:[CDTRmod], 0C3h ; Check for DR0-3 load | ||
| 1485 | ja NotDRS3 ; N: continue | ||
| 1486 | call UnMapLinear ; Y: convert address from our paging | ||
| 1487 | ; linear map, then continue | ||
| 1488 | NotDRS3: | ||
| 1489 | cmp bl, 020h ; Check CRn store | ||
| 1490 | jne ChkDstBX ; N: source not CRn | ||
| 1491 | cmp byte ptr es:[CDTRmod], 0C0h ; Check for CR0 store | ||
| 1492 | je CR0FltrS ; Y: filter it | ||
| 1493 | mov bx, ErrMovCR | ||
| 1494 | jmp short CTRErr ; N: go tell user he did a NoNo | ||
| 1495 | |||
| 1496 | ; Because SMSW shows the PE bit, we let it go through here also | ||
| 1497 | CR0FltrS: | ||
| 1498 | OP32 | ||
| 1499 | and AX, 0FFFFh ; Y: clear | ||
| 1500 | dw 7FFFh ; PG bit if it was set | ||
| 1501 | ChkDstBX: | ||
| 1502 | cmp bh, 3 | ||
| 1503 | jne ChkDstBP | ||
| 1504 | OP32 | ||
| 1505 | mov [bp.MCF_EBX], ax ; mov EBX to stack | ||
| 1506 | jmp short Exit_MovCDTR | ||
| 1507 | ChkDstBP: | ||
| 1508 | cmp bh, 5 | ||
| 1509 | jne ChkDstSI | ||
| 1510 | OP32 | ||
| 1511 | mov [bp.MCF_EBP], ax ; mov EBP to stack | ||
| 1512 | jmp short Exit_MovCDTR | ||
| 1513 | ChkDstSI: | ||
| 1514 | cmp bh, 6 | ||
| 1515 | jne ChkDstAX | ||
| 1516 | OP32 | ||
| 1517 | mov [bp.MCF_ESI], ax ; mov ESI to stack | ||
| 1518 | jmp short Exit_MovCDTR | ||
| 1519 | ChkDstAX: | ||
| 1520 | cmp bh, 0 | ||
| 1521 | jne ChkDstSP | ||
| 1522 | OP32 | ||
| 1523 | mov [bp.MCF_EAX], ax ; mov EAX to stack | ||
| 1524 | jmp short Exit_MovCDTR ; at exit | ||
| 1525 | ChkDstSP: | ||
| 1526 | cmp bh, 4 | ||
| 1527 | jne PutInReg | ||
| 1528 | OP32 | ||
| 1529 | mov [bp.MCF_VMESP], ax ; mov ESP to stack | ||
| 1530 | jmp short Exit_MovCDTR ; at exit | ||
| 1531 | PutInReg: | ||
| 1532 | ; Execute MOV ERn, EAX | ||
| 1533 | or bh, 0C0h ; set register to register move bits | ||
| 1534 | mov es:[regCDTR], bh ; setup load to client's dest register | ||
| 1535 | jmp short PutERn ; clear prefetch so that bh gets there | ||
| 1536 | PutERn: | ||
| 1537 | db 66h | ||
| 1538 | db 089h | ||
| 1539 | regCDTR db 0C0h | ||
| 1540 | |||
| 1541 | |||
| 1542 | Exit_MovCDTR: | ||
| 1543 | pop bp | ||
| 1544 | pop es | ||
| 1545 | assume es:DGROUP | ||
| 1546 | POP_EAX | ||
| 1547 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1548 | CTRErr: | ||
| 1549 | mov ax, PrivErr | ||
| 1550 | pop bp | ||
| 1551 | sub [bp.VTFOE+VMTF_EIP],3 ; VM CS:IP = faulting instruction | ||
| 1552 | pop es | ||
| 1553 | assume es:DGROUP | ||
| 1554 | call ErrHndlr ; If we return here, the user wants to | ||
| 1555 | POP_EAX ; continue in real mode... so go unwind | ||
| 1556 | jmp JumpReal ; the stack and let him continue | ||
| 1557 | Not_MovCDTR: | ||
| 1558 | jmp BadVmTrap | ||
| 1559 | |||
| 1560 | EmMovCDTR endp | ||
| 1561 | |||
| 1562 | ;****************************************************************************** | ||
| 1563 | ;*** EmLOCK - Emulate LOCK prefix | ||
| 1564 | ; | ||
| 1565 | ; This routine is entered if a faulting instruction | ||
| 1566 | ; is a LOCK prefix. | ||
| 1567 | ; | ||
| 1568 | ; ENTRY 386 PROTECTED MODE | ||
| 1569 | ; see common description at top | ||
| 1570 | ; | ||
| 1571 | ; EXIT xfer on to handler for next opcode | ||
| 1572 | ; | ||
| 1573 | EmLOCK proc near | ||
| 1574 | |||
| 1575 | ; 6/15 - Probably should jump to VmInsHandle rather than EmExit to handle a | ||
| 1576 | ; a lock prefix on some other offending instruction. In that case you would | ||
| 1577 | ; have: | ||
| 1578 | ;; or ES:[PrefixFlag],LOCK_FLAG ; set appropriate flag | ||
| 1579 | ;; inc si ; inc VM CS:IP past prefix | ||
| 1580 | ;; jmp VmInsHandle ; and go process offender | ||
| 1581 | ; rather than: | ||
| 1582 | inc si ; set IP past the | ||
| 1583 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1584 | jmp EmExit ; and leave | ||
| 1585 | |||
| 1586 | EmLOCK endp | ||
| 1587 | |||
| 1588 | ;****************************************************************************** | ||
| 1589 | ;*** EmREPNE - handle REPNE prefix | ||
| 1590 | ; | ||
| 1591 | ; We come here if the trapping instruction has | ||
| 1592 | ; a REPNE prefix. We just pass it on to the handler | ||
| 1593 | ; for the next opcode. | ||
| 1594 | ; | ||
| 1595 | ; ENTRY 386 PROTECTED MODE | ||
| 1596 | ; see common description at top | ||
| 1597 | ; | ||
| 1598 | ; EXIT IRET back to VM program | ||
| 1599 | ; | ||
| 1600 | EmREPNE proc near | ||
| 1601 | |||
| 1602 | or ES:[PrefixFlag],REPNE_FLAG ; set appropriate flag | ||
| 1603 | inc si ; inc VM CS:IP past prefix | ||
| 1604 | jmp VmInsHandle ; handle next part of instr | ||
| 1605 | |||
| 1606 | EmREPNE endp | ||
| 1607 | |||
| 1608 | ;*** EmREP - handle REP prefix | ||
| 1609 | ; | ||
| 1610 | ; We come here if the trapping instruction has | ||
| 1611 | ; a REP or REPE prefix. We just pass it on to the handler | ||
| 1612 | ; for the next opcode. | ||
| 1613 | ; | ||
| 1614 | ; ENTRY 386 PROTECTED MODE | ||
| 1615 | ; see common description at top | ||
| 1616 | ; | ||
| 1617 | ; EXIT IRET back to VM program | ||
| 1618 | ; | ||
| 1619 | EmREP proc near | ||
| 1620 | |||
| 1621 | or ES:[PrefixFlag],REP_FLAG ; set appropriate flag | ||
| 1622 | inc si ; inc VM CS:IP past prefix | ||
| 1623 | jmp VmInsHandle ; handle next part of instr | ||
| 1624 | |||
| 1625 | EmREP endp | ||
| 1626 | |||
| 1627 | ;****************************************************************************** | ||
| 1628 | ;*** Prefix_0F - handle 0F overrides | ||
| 1629 | ; | ||
| 1630 | ; This routine is entered if an instruction begins with a 0F prefix. | ||
| 1631 | ; It checks the current opcode against a table of valid 0F-opcodes, | ||
| 1632 | ; and if the opcode is valid, it indexes back into OpTable to jump | ||
| 1633 | ; to the proper opcode handler. | ||
| 1634 | ; (NOTE: This scheme works fine as long as the valid 0F-opcodes | ||
| 1635 | ; continue to have low values allowing this P0F_OpTabx to stay | ||
| 1636 | ; relatively small. If this changes, we probably should go back | ||
| 1637 | ; to using the P0F_OpTab scheme.) | ||
| 1638 | ; | ||
| 1639 | ; ENTRY: 386 Protected Mode | ||
| 1640 | ; EBP,EBX,ESI pushed on stack | ||
| 1641 | ; VM1_GSEL = VM client's stack segment | ||
| 1642 | ; VM2_GSEL = VM client's code segment | ||
| 1643 | ; DS:SI -> faulting prefix = nn (DS = VM2_GSEL) | ||
| 1644 | ; EXIT xfer directly to handler for next opcode | ||
| 1645 | ; | ||
| 1646 | ;*** | ||
| 1647 | P0F_Invalid equ 0FFh ; OpTable vector offset to BadVmTrap | ||
| 1648 | |||
| 1649 | P0F_OpTabx label byte | ||
| 1650 | db 00h ; 00h - LLDT, LTR, SLDT, STR, VERR, VERW | ||
| 1651 | db 02h ; 01h - LIDT, LGDT, LMSW | ||
| 1652 | db 04h ; 02h - LAR | ||
| 1653 | db 06h ; 03h - LSL | ||
| 1654 | db P0F_Invalid ; 04h - BadVmTrap | ||
| 1655 | db 0Ah ; 05h - 286 Loadall | ||
| 1656 | db 0Ch ; 06h - CLTS | ||
| 1657 | db 0Eh ; 07h - 386 Loadall | ||
| 1658 | db P0F_Invalid ; 08h - BadVmTrap | ||
| 1659 | db P0F_Invalid ; 09h - BadVmTrap | ||
| 1660 | db P0F_Invalid ; 0Ah - BadVmTrap | ||
| 1661 | db P0F_Invalid ; 0Bh - BadVmTrap | ||
| 1662 | db P0F_Invalid ; 0Ch - BadVmTrap | ||
| 1663 | db P0F_Invalid ; 0Dh - BadVmTrap | ||
| 1664 | db P0F_Invalid ; 0Eh - BadVmTrap | ||
| 1665 | db P0F_Invalid ; 0Fh - BadVmTrap | ||
| 1666 | db P0F_Invalid ; 10h - BadVmTrap | ||
| 1667 | db P0F_Invalid ; 11h - BadVmTrap | ||
| 1668 | db P0F_Invalid ; 12h - BadVmTrap | ||
| 1669 | db P0F_Invalid ; 13h - BadVmTrap | ||
| 1670 | db P0F_Invalid ; 14h - BadVmTrap | ||
| 1671 | db P0F_Invalid ; 15h - BadVmTrap | ||
| 1672 | db P0F_Invalid ; 16h - BadVmTrap | ||
| 1673 | db P0F_Invalid ; 17h - BadVmTrap | ||
| 1674 | db P0F_Invalid ; 18h - BadVmTrap | ||
| 1675 | db P0F_Invalid ; 19h - BadVmTrap | ||
| 1676 | db P0F_Invalid ; 1Ah - BadVmTrap | ||
| 1677 | db P0F_Invalid ; 1Bh - BadVmTrap | ||
| 1678 | db P0F_Invalid ; 1Ch - BadVmTrap | ||
| 1679 | db P0F_Invalid ; 1Dh - BadVmTrap | ||
| 1680 | db P0F_Invalid ; 1Eh - BadVmTrap | ||
| 1681 | db P0F_Invalid ; 1Fh - BadVmTrap | ||
| 1682 | db 40h ; 20h - CR moves | ||
| 1683 | db 42h ; 21h - DR moves | ||
| 1684 | db 44h ; 22h - CR moves | ||
| 1685 | db 46h ; 23h - DR moves | ||
| 1686 | db 48h ; 24h - TR moves | ||
| 1687 | db P0F_Invalid ; 25h - BadVmTrap | ||
| 1688 | db 4Ch ; 26h - TR moves | ||
| 1689 | P0F_OpTabx_Size equ $-P0F_OpTabx | ||
| 1690 | |||
| 1691 | ;*** | ||
| 1692 | Prefix_0F proc near | ||
| 1693 | inc si ; inc DS:SI past prefix | ||
| 1694 | mov bl,[si] ; BL = opcode | ||
| 1695 | cmp bl, P0F_OpTabx_Size | ||
| 1696 | jae Bad_0F | ||
| 1697 | mov bh,0 ; BX = opcode | ||
| 1698 | mov bl, cs:P0F_OpTabx[bx] | ||
| 1699 | cmp bl, P0F_Invalid | ||
| 1700 | je Bad_0F | ||
| 1701 | or es:[PrefixFlag],P0F_FLAG ; set appropriate flag | ||
| 1702 | jmp cs:OpTable[bx] ; enter instr emulation routine | ||
| 1703 | |||
| 1704 | Bad_0F: | ||
| 1705 | jmp BadVmTrap | ||
| 1706 | |||
| 1707 | Prefix_0F endp | ||
| 1708 | |||
| 1709 | ;****************************************************************************** | ||
| 1710 | ;*** CSOverride - handle CS overrides | ||
| 1711 | ; | ||
| 1712 | ; This routine is entered if a faulting instruction | ||
| 1713 | ; has a CS override. | ||
| 1714 | ; | ||
| 1715 | ; ENTRY 386 PROTECTED MODE | ||
| 1716 | ; see common description at top | ||
| 1717 | ; | ||
| 1718 | ; EXIT xfer on to handler for next opcode | ||
| 1719 | ; | ||
| 1720 | CSOverride proc near | ||
| 1721 | |||
| 1722 | or ES:[PrefixFlag],CS_FLAG ; set appropriate flag | ||
| 1723 | inc si ; inc VM CS:IP past prefix | ||
| 1724 | jmp VmInsHandle ; handle next part of instr | ||
| 1725 | |||
| 1726 | CSOverride endp | ||
| 1727 | |||
| 1728 | ;****************************************************************************** | ||
| 1729 | ;*** DSOverride - handle DS overrides | ||
| 1730 | ; | ||
| 1731 | ; This routine is entered if a faulting instruction | ||
| 1732 | ; has a DS override. | ||
| 1733 | ; | ||
| 1734 | ; ENTRY 386 PROTECTED MODE | ||
| 1735 | ; see common description at top | ||
| 1736 | ; | ||
| 1737 | ; EXIT xfer on to handler for next opcode | ||
| 1738 | ; | ||
| 1739 | DSOverride proc near | ||
| 1740 | |||
| 1741 | or ES:[PrefixFlag],DS_FLAG ; set appropriate flag | ||
| 1742 | inc si ; inc VM CS:IP past prefix | ||
| 1743 | jmp VmInsHandle ; handle next part of instr | ||
| 1744 | |||
| 1745 | DSOverride endp | ||
| 1746 | |||
| 1747 | ;****************************************************************************** | ||
| 1748 | ;*** ESOverride - handle ES overrides | ||
| 1749 | ; | ||
| 1750 | ; This routine is entered if a faulting instruction | ||
| 1751 | ; has a ES override or a MOV TRn, Rn opcode | ||
| 1752 | ; | ||
| 1753 | ; ENTRY 386 PROTECTED MODE | ||
| 1754 | ; see common description at top | ||
| 1755 | ; | ||
| 1756 | ; EXIT xfer on to handler for next opcode | ||
| 1757 | ; | ||
| 1758 | |||
| 1759 | ESOverride proc near | ||
| 1760 | |||
| 1761 | test ES:[PrefixFlag],P0F_FLAG ; only for TR emulation | ||
| 1762 | jz ESO1 ; only for TR emulation | ||
| 1763 | jmp EmMovCDTR ; only for TR emulation | ||
| 1764 | ESO1: | ||
| 1765 | or ES:[PrefixFlag],ES_FLAG ; set appropriate flag | ||
| 1766 | inc si ; inc VM CS:IP past prefix | ||
| 1767 | jmp VmInsHandle ; handle next part of instr | ||
| 1768 | |||
| 1769 | ESOverride endp | ||
| 1770 | |||
| 1771 | ;****************************************************************************** | ||
| 1772 | ;*** SSOverride - handle SS overrides | ||
| 1773 | ; | ||
| 1774 | ; This routine is entered if a faulting instruction | ||
| 1775 | ; has a SS override. | ||
| 1776 | ; | ||
| 1777 | ; ENTRY 386 PROTECTED MODE | ||
| 1778 | ; see common description at top | ||
| 1779 | ; | ||
| 1780 | ; EXIT xfer on to handler for next opcode | ||
| 1781 | ; | ||
| 1782 | |||
| 1783 | SSOverride proc near | ||
| 1784 | |||
| 1785 | or ES:[PrefixFlag],SS_FLAG ; set appropriate flag | ||
| 1786 | ;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix | ||
| 1787 | inc si ; inc VM CS:IP past prefix | ||
| 1788 | jmp VmInsHandle ; handle next part of instr | ||
| 1789 | |||
| 1790 | SSOverride endp | ||
| 1791 | |||
| 1792 | ;****************************************************************************** | ||
| 1793 | ;*** FSOverride - handle FS overrides | ||
| 1794 | ; | ||
| 1795 | ; This routine is entered if a faulting instruction | ||
| 1796 | ; has a FS override. | ||
| 1797 | ; | ||
| 1798 | ; ENTRY 386 PROTECTED MODE | ||
| 1799 | ; see common description at top | ||
| 1800 | ; | ||
| 1801 | ; EXIT xfer on to handler for next opcode | ||
| 1802 | ; | ||
| 1803 | |||
| 1804 | FSOverride proc near | ||
| 1805 | |||
| 1806 | or ES:[PrefixFlag],FS_FLAG ; set appropriate flag | ||
| 1807 | ;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix | ||
| 1808 | inc si ; inc VM CS:IP past prefix | ||
| 1809 | jmp VmInsHandle ; handle next part of instr | ||
| 1810 | |||
| 1811 | FSOverride endp | ||
| 1812 | |||
| 1813 | ;****************************************************************************** | ||
| 1814 | ;*** GSOverride - handle GS overrides | ||
| 1815 | ; | ||
| 1816 | ; This routine is entered if a faulting instruction | ||
| 1817 | ; has a GS override. | ||
| 1818 | ; | ||
| 1819 | ; ENTRY 386 PROTECTED MODE | ||
| 1820 | ; see common description at top | ||
| 1821 | ; | ||
| 1822 | ; EXIT xfer on to handler for next opcode | ||
| 1823 | ; | ||
| 1824 | |||
| 1825 | GSOverride proc near | ||
| 1826 | |||
| 1827 | or ES:[PrefixFlag],GS_FLAG ; set appropriate flag | ||
| 1828 | ;; inc [bp.VTFOE+VMTF_EIP] ; inc VM CS:IP past prefix | ||
| 1829 | inc si ; inc VM CS:IP past prefix | ||
| 1830 | jmp VmInsHandle ; handle next part of instr | ||
| 1831 | |||
| 1832 | GSOverride endp | ||
| 1833 | |||
| 1834 | ;****************************************************************************** | ||
| 1835 | ;*** EmINSB - emulate IN byte string | ||
| 1836 | ; | ||
| 1837 | ; This routine emulates the IN byte string instruction | ||
| 1838 | ; *** this routine emulates REP instructions entirely *** | ||
| 1839 | ; *** within protected mode. This effectively masks out *** | ||
| 1840 | ; *** interupts between bytes in the operation, even *** | ||
| 1841 | ; *** if the VM code had interrupts on. *** | ||
| 1842 | ; | ||
| 1843 | ; ENTRY 386 PROTECTED MODE | ||
| 1844 | ; see common description at top | ||
| 1845 | ; | ||
| 1846 | ; EXIT IRET back to VM program | ||
| 1847 | ; | ||
| 1848 | ; USES ES,BX,DI | ||
| 1849 | ; | ||
| 1850 | |||
| 1851 | EmINSB proc near | ||
| 1852 | ; | ||
| 1853 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 1854 | inc si ; set IP past the | ||
| 1855 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1856 | ; | ||
| 1857 | ; | ||
| 1858 | ; Build a selector (VM1_GSEL) to client's ES segment. VM1_GSEL is already set | ||
| 1859 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1860 | ; | ||
| 1861 | mov bx,GDTD_GSEL | ||
| 1862 | mov ds,bx ; DS = GDT selector | ||
| 1863 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (segment form) | ||
| 1864 | shl bx,4 ; BX = low 16 bits of base | ||
| 1865 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 1866 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (again) | ||
| 1867 | shr bx,4 ; BH = high 8 bits of base | ||
| 1868 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 1869 | mov bx,VM1_GSEL | ||
| 1870 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 1871 | mov es,bx ; ES = VM ES | ||
| 1872 | jnz EINSB_loop ; Y: go do rep instruction | ||
| 1873 | insb ; N: do single instruction | ||
| 1874 | jmp EINSB_exit ; and leave | ||
| 1875 | EINSB_loop: | ||
| 1876 | cld ; assume cld | ||
| 1877 | mov bx,DF_FLAG | ||
| 1878 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 1879 | jz EINSB_rep ; Y: go ahead | ||
| 1880 | std ; N: set it | ||
| 1881 | EINSB_rep: | ||
| 1882 | rep insb ; rep version | ||
| 1883 | |||
| 1884 | EINSB_Exit: ; | ||
| 1885 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1886 | ; | ||
| 1887 | EmINSB endp | ||
| 1888 | |||
| 1889 | |||
| 1890 | ;****************************************************************************** | ||
| 1891 | ;*** EmINSW - emulate IN word string | ||
| 1892 | ; | ||
| 1893 | ; This routine emulates the IN word string instruction | ||
| 1894 | ; *** this routine emulates REP instructions entirely *** | ||
| 1895 | ; *** within protected mode. This effectively masks out *** | ||
| 1896 | ; *** interupts between bytes in the operation, even *** | ||
| 1897 | ; *** if the VM code had interrupts on. *** | ||
| 1898 | ; | ||
| 1899 | ; ENTRY 386 PROTECTED MODE | ||
| 1900 | ; see common description at top | ||
| 1901 | ; | ||
| 1902 | ; EXIT IRET back to VM program | ||
| 1903 | ; | ||
| 1904 | ; USES ES,BX,DI | ||
| 1905 | ; | ||
| 1906 | |||
| 1907 | EmINSW proc near | ||
| 1908 | ; | ||
| 1909 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 1910 | inc si ; set IP past the | ||
| 1911 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1912 | ; | ||
| 1913 | ; | ||
| 1914 | ; | ||
| 1915 | ; Build a selector (VM1_GSEL) to client's ES segment. VM1_GSEL is already set | ||
| 1916 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1917 | ; | ||
| 1918 | mov bx,GDTD_GSEL | ||
| 1919 | mov ds,bx ; DS = GDT selector | ||
| 1920 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (segment form) | ||
| 1921 | shl bx,4 ; BX = low 16 bits of base | ||
| 1922 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 1923 | mov bx,[bp.VTFOE+VMTF_ES] ; BX = VM ES (again) | ||
| 1924 | shr bx,4 ; BH = high 8 bits of base | ||
| 1925 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 1926 | mov bx,VM1_GSEL | ||
| 1927 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 1928 | mov es,bx ; ES = VM ES | ||
| 1929 | jnz EINSW_loop ; Y: go do rep instruction | ||
| 1930 | insw ; N: do single instruction | ||
| 1931 | jmp EINSW_exit ; and leave | ||
| 1932 | EINSW_loop: | ||
| 1933 | cld ; assume cld | ||
| 1934 | mov bx,DF_FLAG | ||
| 1935 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 1936 | jz EINSW_rep ; Y: go ahead | ||
| 1937 | std ; N: set it | ||
| 1938 | EINSW_rep: | ||
| 1939 | rep insw ; rep version | ||
| 1940 | |||
| 1941 | EINSW_Exit: ; | ||
| 1942 | jmp EmExit ; *** RETURN *** to VM client | ||
| 1943 | ; | ||
| 1944 | EmINSW endp | ||
| 1945 | |||
| 1946 | |||
| 1947 | ;****************************************************************************** | ||
| 1948 | ;*** EmOUTSB - emulate OUT byte string | ||
| 1949 | ; | ||
| 1950 | ; This routine emulates the OUT byte string instruction | ||
| 1951 | ; *** this routine emulates REP instructions entirely *** | ||
| 1952 | ; *** within protected mode. This effectively masks out *** | ||
| 1953 | ; *** interupts between bytes in the operation, even *** | ||
| 1954 | ; *** if the VM code had interrupts on. *** | ||
| 1955 | ; | ||
| 1956 | ; ENTRY 386 PROTECTED MODE | ||
| 1957 | ; see common description at top | ||
| 1958 | ; | ||
| 1959 | ; EXIT IRET back to VM program | ||
| 1960 | ; | ||
| 1961 | ; USES DS,BX,SI | ||
| 1962 | ; | ||
| 1963 | |||
| 1964 | EmOUTSB proc near | ||
| 1965 | ; | ||
| 1966 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 1967 | inc si ; set IP past the | ||
| 1968 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 1969 | ; | ||
| 1970 | ; restore SI | ||
| 1971 | ; | ||
| 1972 | pop si | ||
| 1973 | push si | ||
| 1974 | ; | ||
| 1975 | ; Build a selector (VM1_GSEL) to client's DS segment. VM1_GSEL is already set | ||
| 1976 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 1977 | ; | ||
| 1978 | mov bx,GDTD_GSEL | ||
| 1979 | mov ds,bx ; DS = GDT selector | ||
| 1980 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (segment form) | ||
| 1981 | shl bx,4 ; BX = low 16 bits of base | ||
| 1982 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 1983 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (again) | ||
| 1984 | shr bx,4 ; BH = high 8 bits of base | ||
| 1985 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 1986 | mov bx,VM1_GSEL | ||
| 1987 | mov ds,bx ; DS = VM DS | ||
| 1988 | |||
| 1989 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 1990 | jnz EOUTSB_loop ; Y: go do rep instruction | ||
| 1991 | outsb ; N: do single instruction | ||
| 1992 | jmp EOUTSB_exit ; and leave | ||
| 1993 | EOUTSB_loop: | ||
| 1994 | cld ; assume cld | ||
| 1995 | mov bx,DF_FLAG | ||
| 1996 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 1997 | jz EOUTSB_rep ; Y: go ahead | ||
| 1998 | std ; N: set it | ||
| 1999 | EOUTSB_rep: | ||
| 2000 | rep outsb ; rep version | ||
| 2001 | |||
| 2002 | EOUTSB_Exit: ; | ||
| 2003 | jmp EmExit ; *** RETURN *** to VM client | ||
| 2004 | ; | ||
| 2005 | EmOUTSB endp | ||
| 2006 | |||
| 2007 | |||
| 2008 | ;****************************************************************************** | ||
| 2009 | ;*** EmOUTSW - emulate OUT word string | ||
| 2010 | ; | ||
| 2011 | ; This routine emulates the OUT word string instruction | ||
| 2012 | ; *** this routine emulates REP instructions entirely *** | ||
| 2013 | ; *** within protected mode. This effectively masks out *** | ||
| 2014 | ; *** interupts between bytes in the operation, even *** | ||
| 2015 | ; *** if the VM code had interrupts on. *** | ||
| 2016 | ; | ||
| 2017 | ; ENTRY 386 PROTECTED MODE | ||
| 2018 | ; see common description at top | ||
| 2019 | ; | ||
| 2020 | ; EXIT IRET back to VM program | ||
| 2021 | ; | ||
| 2022 | ; USES DS,BX,SI | ||
| 2023 | ; | ||
| 2024 | |||
| 2025 | EmOUTSW proc near | ||
| 2026 | ; | ||
| 2027 | ;; inc [bp.VTFOE+VMTF_EIP] ; set IP past the instruction we emulate | ||
| 2028 | inc si ; set IP past the | ||
| 2029 | mov [bp.VTFOE+VMTF_EIP], si ; instruction we emulate | ||
| 2030 | ; | ||
| 2031 | ; restore SI | ||
| 2032 | ; | ||
| 2033 | pop si | ||
| 2034 | push si | ||
| 2035 | ; | ||
| 2036 | ; | ||
| 2037 | ; Build a selector (VM1_GSEL) to client's DS segment. VM1_GSEL is already set | ||
| 2038 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 2039 | ; | ||
| 2040 | mov bx,GDTD_GSEL | ||
| 2041 | mov ds,bx ; DS = GDT selector | ||
| 2042 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (segment form) | ||
| 2043 | shl bx,4 ; BX = low 16 bits of base | ||
| 2044 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 2045 | mov bx,[bp.VTFOE+VMTF_DS] ; BX = VM DS (again) | ||
| 2046 | shr bx,4 ; BH = high 8 bits of base | ||
| 2047 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 2048 | mov bx,VM1_GSEL | ||
| 2049 | mov ds,bx ; DS = VM DS | ||
| 2050 | |||
| 2051 | test ES:[PrefixFlag],REP_FLAG ;Q: REP prefix active ? | ||
| 2052 | jnz EOUTSW_loop ; Y: go do rep instruction | ||
| 2053 | outsw ; N: do single instruction | ||
| 2054 | jmp EOUTSW_exit ; and leave | ||
| 2055 | EOUTSW_loop: | ||
| 2056 | cld ; assume cld | ||
| 2057 | mov bx,DF_FLAG | ||
| 2058 | test bx,word ptr [bp.VTFOE+VMTF_EFLAGS] ;Q: client's DF bit is CLD? | ||
| 2059 | jz EOUTSW_rep ; Y: go ahead | ||
| 2060 | std ; N: set it | ||
| 2061 | EOUTSW_rep: | ||
| 2062 | rep outsw ; rep version | ||
| 2063 | |||
| 2064 | EOUTSW_Exit: ; | ||
| 2065 | jmp EmExit ; *** RETURN *** to VM client | ||
| 2066 | ; | ||
| 2067 | EmOUTSW endp | ||
| 2068 | |||
| 2069 | ;****************************************************************************** | ||
| 2070 | ;*** EmMOVSW - emulate MOV word string | ||
| 2071 | ; | ||
| 2072 | ; This routine emulates the MOV word string instruction | ||
| 2073 | ; specifically to handle the RASH Rules (Jokes) emulation. | ||
| 2074 | ; For now, the only reason for doing this is to allow a bug | ||
| 2075 | ; in PC Week's benchmark tests to FAIL "properly" so that the test | ||
| 2076 | ; works. (Unbelievable!) | ||
| 2077 | ; | ||
| 2078 | ; NOTE: After testing, if the ROM properly emulates the RASH | ||
| 2079 | ; requirements, this routine should be reduced to the Reflect6 | ||
| 2080 | ; function. | ||
| 2081 | ; | ||
| 2082 | ; ENTRY 386 PROTECTED MODE | ||
| 2083 | ; see common description at top | ||
| 2084 | ; | ||
| 2085 | ; EXIT IRET back to VM program | ||
| 2086 | ; | ||
| 2087 | ; USES DS,BX,SI | ||
| 2088 | ; | ||
| 2089 | EmMOVSW proc near | ||
| 2090 | mov bx, sp | ||
| 2091 | cmp di, 0FFFFh ; Q:Does either Di | ||
| 2092 | je EmWRASH | ||
| 2093 | cmp ss:[bx.GPF_ESI], 0FFFFh ; or SI = FFFF? | ||
| 2094 | je EmWRASH ; Y:Assume RASH GPfault | ||
| 2095 | Reflect6: | ||
| 2096 | mov es:[RefNum], 06h | ||
| 2097 | RefToROM: | ||
| 2098 | POP_ESI ; N: clean up the stack, | ||
| 2099 | POP_EBX | ||
| 2100 | POP_EBP | ||
| 2101 | add sp,4 ; throw away error code, | ||
| 2102 | PUSH_EBP | ||
| 2103 | mov bp,sp ; reset BP to stack frame | ||
| 2104 | push es:[RefNum] ; push the trap number | ||
| 2105 | jmp hw_int ; and, Reflect to ROM | ||
| 2106 | EmWRASH: | ||
| 2107 | test es:[PrefixFlag], REPS_FLAG ; Q:Is this a REP of REPNE? | ||
| 2108 | jz EMWCXok ; N: don't change CX | ||
| 2109 | inc cx | ||
| 2110 | EMWCXok: | ||
| 2111 | mov ax, 2 ; assume up counter | ||
| 2112 | test [bp.VTFOE+VMTF_EFLAGS], DF_FLAG | ||
| 2113 | jz EMWUpdtSI | ||
| 2114 | not ax | ||
| 2115 | EMWUpdtSI: | ||
| 2116 | mov si, ss:[bx.GPF_ESI] | ||
| 2117 | add ss:[bx.GPF_ESI], ax ; verify neg??? | ||
| 2118 | cmp si, 0FFFFh ; Q:Did SI cause the GP fault | ||
| 2119 | jne EMWUpdtDI ; N:Go fixup DI and CX | ||
| 2120 | jmp short EMW_Exit ; Y:We're done | ||
| 2121 | EMWUpdtDI: | ||
| 2122 | test es:[PrefixFlag], REPS_FLAG ; Q:Is this a REP of REPNE? | ||
| 2123 | jz EMWCXok2 ; N: don't change CX | ||
| 2124 | inc cx | ||
| 2125 | EMWCXok2: | ||
| 2126 | add di, ax ; verify neg??? | ||
| 2127 | EMW_Exit: | ||
| 2128 | jmp EmExit ; *** RETURN *** to VM client | ||
| 2129 | ; | ||
| 2130 | EmMOVSW endp | ||
| 2131 | |||
| 2132 | _TEXT ends | ||
| 2133 | |||
| 2134 | end | ||
| 2135 | |||
diff --git a/v4.0/src/MEMM/MEMM/VMTRAP.ASM b/v4.0/src/MEMM/MEMM/VMTRAP.ASM new file mode 100644 index 0000000..095ebef --- /dev/null +++ b/v4.0/src/MEMM/MEMM/VMTRAP.ASM | |||
| @@ -0,0 +1,791 @@ | |||
| 1 | |||
| 2 | |||
| 3 | page 58,132 | ||
| 4 | ;****************************************************************************** | ||
| 5 | title VMTRAP - 386 Virtual Mode interrupt handler routines | ||
| 6 | ;****************************************************************************** | ||
| 7 | ; | ||
| 8 | ; (C) Copyright MICROSOFT Corp. 1986 | ||
| 9 | ; | ||
| 10 | ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver | ||
| 11 | ; | ||
| 12 | ; Module: VMTRAP - 386 Virtual Mode interrupt handler routines | ||
| 13 | ; | ||
| 14 | ; Version: 0.02 | ||
| 15 | ; | ||
| 16 | ; Date: January 26, 1986 | ||
| 17 | ; | ||
| 18 | ; Author: | ||
| 19 | ; | ||
| 20 | ;****************************************************************************** | ||
| 21 | ; | ||
| 22 | ; Change log: | ||
| 23 | ; | ||
| 24 | ; DATE REVISION DESCRIPTION | ||
| 25 | ; -------- -------- ------------------------------------------------------ | ||
| 26 | ; 01/26/86 Original | ||
| 27 | ; 02/05/86 A- Added int 15h trap to move block function. | ||
| 28 | ; 05/12/86 A Cleanup and segment reorganization | ||
| 29 | ; 06/19/86 0.01 Added emul_reflect entry point for preserving | ||
| 30 | ; IF and TF flags bits on reflections done by | ||
| 31 | ; instruction emulators. | ||
| 32 | ; 06/28/86 0.02 Name change from MEMM386 to MEMM | ||
| 33 | ; 07/20/88 Removed debugger codes (pc) | ||
| 34 | ; | ||
| 35 | ;****************************************************************************** | ||
| 36 | ; | ||
| 37 | ; Functional Description: | ||
| 38 | ; | ||
| 39 | ; This module contains the interrupt and trap handlers for Virtual DOS. | ||
| 40 | ; | ||
| 41 | ; Note that a conscious decision has been made to attempt to field the | ||
| 42 | ; Master 8259 interrupts at the normal PC location (vectors 8 - F). The | ||
| 43 | ; main problem is that these overlap CPU exception vectors. While the | ||
| 44 | ; 8259 base vector address could be changed (there's lots of room in the | ||
| 45 | ; IDT, since we're fielding S/W INTs through GP 13), the primary reason | ||
| 46 | ; for not doing so is to avoid any potential trouble with an application | ||
| 47 | ; reprogramming the 8259. We don't know of any that do, and you could | ||
| 48 | ; trap them if they tried anyway. | ||
| 49 | ; | ||
| 50 | ; "to do:" marks potential holes/things to consider | ||
| 51 | ; | ||
| 52 | ;****************************************************************************** | ||
| 53 | .lfcond ; list false conditionals | ||
| 54 | .386p | ||
| 55 | page | ||
| 56 | ;****************************************************************************** | ||
| 57 | ; P U B L I C D E C L A R A T I O N S | ||
| 58 | ;****************************************************************************** | ||
| 59 | ; | ||
| 60 | public VmTrap ; module label | ||
| 61 | |||
| 62 | public hw_int | ||
| 63 | public emul_reflect | ||
| 64 | |||
| 65 | public vm_trap00 | ||
| 66 | public vm_trap01 | ||
| 67 | public vm_trap02 | ||
| 68 | public vm_trap03 | ||
| 69 | public vm_trap04 | ||
| 70 | public vm_trap05 | ||
| 71 | public vm_trap06 | ||
| 72 | public vm_trap07 | ||
| 73 | public vm_trap08 | ||
| 74 | public vm_trap09 | ||
| 75 | public vm_trap0a | ||
| 76 | public vm_trap0b | ||
| 77 | public vm_trap0c | ||
| 78 | public vm_trap0d | ||
| 79 | public vm_trap0e | ||
| 80 | public vm_trap0f | ||
| 81 | public vm_trap10 | ||
| 82 | public vm_trap50 | ||
| 83 | public vm_trap51 | ||
| 84 | public vm_trap52 | ||
| 85 | public vm_trap53 | ||
| 86 | public vm_trap54 | ||
| 87 | public vm_trap55 | ||
| 88 | public vm_trap56 | ||
| 89 | public vm_trap57 | ||
| 90 | public vm_trap70 | ||
| 91 | public vm_trap71 | ||
| 92 | public vm_trap72 | ||
| 93 | public vm_trap73 | ||
| 94 | public vm_trap74 | ||
| 95 | public vm_trap75 | ||
| 96 | public vm_trap76 | ||
| 97 | public vm_trap77 | ||
| 98 | |||
| 99 | page | ||
| 100 | ;****************************************************************************** | ||
| 101 | ; E X T E R N A L R E F E R E N C E S | ||
| 102 | ;****************************************************************************** | ||
| 103 | ; | ||
| 104 | _TEXT segment | ||
| 105 | extrn VmFault:near ; V Mode GP fault handler (VMINST) | ||
| 106 | extrn ErrHndlr:near ; Error Handler (ERRHNDLR) | ||
| 107 | extrn DisableNMI:near ; Disable NMI for NMI trap handler | ||
| 108 | _TEXT ends | ||
| 109 | page | ||
| 110 | ;****************************************************************************** | ||
| 111 | ; I N C L U D E F I L E S | ||
| 112 | ;****************************************************************************** | ||
| 113 | ; | ||
| 114 | include VDMseg.inc | ||
| 115 | include VDMsel.inc | ||
| 116 | include vm386.inc | ||
| 117 | include pic_def.equ | ||
| 118 | include instr386.inc | ||
| 119 | include oemdep.inc | ||
| 120 | |||
| 121 | page | ||
| 122 | ;****************************************************************************** | ||
| 123 | ; L O C A L C O N S T A N T S | ||
| 124 | ;****************************************************************************** | ||
| 125 | ; | ||
| 126 | FALSE equ 0 | ||
| 127 | TRUE equ not FALSE | ||
| 128 | |||
| 129 | ProcessExcep macro ExcepNum | ||
| 130 | mov bx, ExcepNum | ||
| 131 | mov ax, ExcpErr | ||
| 132 | jmp ErrHndlr | ||
| 133 | endm | ||
| 134 | ; | ||
| 135 | ;****************************************************************************** | ||
| 136 | ; S E G M E N T D E F I N I T I O N | ||
| 137 | ;****************************************************************************** | ||
| 138 | ; | ||
| 139 | ABS0 segment at 0000h | ||
| 140 | ABS0 ends | ||
| 141 | ; | ||
| 142 | ;------------------------------------------------------------------------------ | ||
| 143 | _TEXT segment | ||
| 144 | assume cs:_TEXT, ds:NOTHING, es:NOTHING, ss:NOTHING | ||
| 145 | VmTrap label byte | ||
| 146 | ; | ||
| 147 | db 'WCC' | ||
| 148 | ; | ||
| 149 | page | ||
| 150 | ;****************************************************************************** | ||
| 151 | ; CPU: Divide error fault | ||
| 152 | ; | ||
| 153 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 154 | ; No error code on stack | ||
| 155 | ; EXIT: to handler or debugger as appropriate | ||
| 156 | ; USED: | ||
| 157 | ; STACK: | ||
| 158 | ;------------------------------------------------------------------------------ | ||
| 159 | vm_trap00 proc near | ||
| 160 | PUSH_EBP | ||
| 161 | mov bp,sp | ||
| 162 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 163 | jz vmt0_dexit ; N: exit to debugger | ||
| 164 | push 0000 ; Y: interrupt 00 | ||
| 165 | jmp hw_int ; reflect it to virtual mode | ||
| 166 | vmt0_dexit: | ||
| 167 | ProcessExcep ErrDIV | ||
| 168 | vm_trap00 endp | ||
| 169 | |||
| 170 | ;****************************************************************************** | ||
| 171 | ; CPU: Debug trap | ||
| 172 | ; | ||
| 173 | ; Traps from Virtual mode are reflected to virtual mode. Unfortunately | ||
| 174 | ; this breaks the debugger's ability to GO and TRACE the VM program. | ||
| 175 | ; | ||
| 176 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 177 | ; No error code on stack | ||
| 178 | ; EXIT: to handler or debugger as appropriate | ||
| 179 | ; USED: | ||
| 180 | ; STACK: | ||
| 181 | ;------------------------------------------------------------------------------ | ||
| 182 | vm_trap01 proc near | ||
| 183 | PUSH_EBP | ||
| 184 | mov bp,sp | ||
| 185 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 186 | jz vmt1_dexit ; N: exit to debugger | ||
| 187 | push 0001 ; Y: interrupt 01 | ||
| 188 | jmp hw_int ; reflect it to virtual mode | ||
| 189 | vmt1_dexit: | ||
| 190 | ProcessExcep ErrINT1 | ||
| 191 | vm_trap01 endp | ||
| 192 | |||
| 193 | ;****************************************************************************** | ||
| 194 | ; H/W: NMI | ||
| 195 | ; | ||
| 196 | ; For now, this always traps to the debugger. It's a general purpose hook | ||
| 197 | ; to let the debugger get control via an NMI button. | ||
| 198 | ; | ||
| 199 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 200 | ; No error code on stack | ||
| 201 | ; EXIT: to handler or debugger as appropriate | ||
| 202 | ; USED: | ||
| 203 | ; STACK: | ||
| 204 | ;------------------------------------------------------------------------------ | ||
| 205 | vm_trap02 proc near | ||
| 206 | PUSH_EBP | ||
| 207 | mov bp,sp | ||
| 208 | |||
| 209 | call DisableNMI | ||
| 210 | |||
| 211 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 212 | jz vmt2_parity ; N: error/debug trap | ||
| 213 | ; Y: reflect it/debugger | ||
| 214 | push 02 ; reflect it | ||
| 215 | jmp hw_int | ||
| 216 | vmt2_parity: | ||
| 217 | ProcessExcep ErrNMI | ||
| 218 | |||
| 219 | vm_trap02 endp | ||
| 220 | |||
| 221 | ;****************************************************************************** | ||
| 222 | ; CPU: Breakpoint trap (INT 3 instruction) | ||
| 223 | ; | ||
| 224 | ; Traps from Virtual mode are reflected to virtual mode. Unfortunately | ||
| 225 | ; this breaks the debugger's ability to GO and TRACE the VM program. | ||
| 226 | ; | ||
| 227 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 228 | ; No error code on stack | ||
| 229 | ; EXIT: to handler or debugger as appropriate | ||
| 230 | ; USED: | ||
| 231 | ; STACK: | ||
| 232 | ;------------------------------------------------------------------------------ | ||
| 233 | vm_trap03 proc near | ||
| 234 | ProcessExcep ErrINT3 | ||
| 235 | vm_trap03 endp | ||
| 236 | |||
| 237 | ;****************************************************************************** | ||
| 238 | ; CPU: Overflow trap (INTO instruction) | ||
| 239 | ; | ||
| 240 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 241 | ; No error code on stack | ||
| 242 | ; EXIT: to handler or debugger as appropriate | ||
| 243 | ; USED: | ||
| 244 | ; STACK: | ||
| 245 | ;------------------------------------------------------------------------------ | ||
| 246 | vm_trap04 proc near | ||
| 247 | ProcessExcep ErrINTO | ||
| 248 | vm_trap04 endp | ||
| 249 | |||
| 250 | |||
| 251 | ;****************************************************************************** | ||
| 252 | ; CPU: Array bounds fault | ||
| 253 | ; | ||
| 254 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 255 | ; No error code on stack | ||
| 256 | ; EXIT: to handler or debugger as appropriate | ||
| 257 | ; USED: | ||
| 258 | ; STACK: | ||
| 259 | ;------------------------------------------------------------------------------ | ||
| 260 | vm_trap05 proc near | ||
| 261 | PUSH_EBP | ||
| 262 | mov bp,sp | ||
| 263 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 264 | jz vmt5_dexit ; N: exit to debugger | ||
| 265 | push 0005 ; Y: interrupt 01 | ||
| 266 | jmp hw_int ; reflect it to virtual mode | ||
| 267 | vmt5_dexit: | ||
| 268 | ProcessExcep ErrBounds | ||
| 269 | vm_trap05 endp | ||
| 270 | |||
| 271 | ;****************************************************************************** | ||
| 272 | ; CPU: Invalid Opcode fault | ||
| 273 | ; | ||
| 274 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 275 | ; No error code on stack | ||
| 276 | ; EXIT: to handler or debugger as appropriate | ||
| 277 | ; USED: | ||
| 278 | ; STACK: | ||
| 279 | ; | ||
| 280 | ; add Invalid instruction emulator ??? (specifically LOCK prefix) | ||
| 281 | ; | ||
| 282 | ;------------------------------------------------------------------------------ | ||
| 283 | vm_trap06 proc near | ||
| 284 | push 0 ; align stack with error offset | ||
| 285 | push 0 ; for VmFault | ||
| 286 | PUSH_EBP | ||
| 287 | mov bp,sp | ||
| 288 | test [bp.VTFOE+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 289 | jz vmt6_dexit ; N: exit to debugger | ||
| 290 | jmp VmFault ; Y: enter VM 06 Invalid handler | ||
| 291 | |||
| 292 | vmt6_dexit: | ||
| 293 | ProcessExcep ErrOpCode | ||
| 294 | vm_trap06 endp | ||
| 295 | |||
| 296 | ;****************************************************************************** | ||
| 297 | ; CPU: Coprocessor not present fault | ||
| 298 | ; | ||
| 299 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 300 | ; No error code on stack | ||
| 301 | ; EXIT: to handler or debugger as appropriate | ||
| 302 | ; USED: | ||
| 303 | ; STACK: | ||
| 304 | ;------------------------------------------------------------------------------ | ||
| 305 | vm_trap07 proc near | ||
| 306 | PUSH_EBP | ||
| 307 | mov bp,sp | ||
| 308 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 309 | jz vmt7_dexit ; N: exit to debugger | ||
| 310 | push 0007 ; Y: interrupt 07 | ||
| 311 | jmp hw_int ; reflect it to virtual mode | ||
| 312 | vmt7_dexit: | ||
| 313 | ProcessExcep ErrCoPNA | ||
| 314 | vm_trap07 endp | ||
| 315 | |||
| 316 | |||
| 317 | ;****************************************************************************** | ||
| 318 | ; CPU: Double Fault | ||
| 319 | ; H/W: IRQ0 - System timer | ||
| 320 | ; | ||
| 321 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 322 | ; Error Code on stack = 0000 | ||
| 323 | ; EXIT: to handler or debugger as appropriate | ||
| 324 | ; USED: | ||
| 325 | ; STACK: | ||
| 326 | ;------------------------------------------------------------------------------ | ||
| 327 | vm_trap08 proc near | ||
| 328 | PUSH_EBP | ||
| 329 | mov bp,sp | ||
| 330 | cmp sp,VMT_STACK ; Q: H/W interrupt from VM ? | ||
| 331 | jne vmt8_dexit ; N: exit to debugger | ||
| 332 | push 0008 ; Y: interrupt 8 | ||
| 333 | jmp hw_int ; reflect it to virtual mode | ||
| 334 | vmt8_dexit: | ||
| 335 | ProcessExcep ErrDouble | ||
| 336 | vm_trap08 endp | ||
| 337 | |||
| 338 | |||
| 339 | ;****************************************************************************** | ||
| 340 | ; CPU: (none for 386) | ||
| 341 | ; H/W: IRQ1 - Keyboard | ||
| 342 | ; | ||
| 343 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 344 | ; No error code on stack | ||
| 345 | ; EXIT: to handler or debugger as appropriate | ||
| 346 | ; USED: | ||
| 347 | ; STACK: | ||
| 348 | ;------------------------------------------------------------------------------ | ||
| 349 | vm_trap09 proc near | ||
| 350 | PUSH_EBP | ||
| 351 | mov bp,sp | ||
| 352 | push 0009 ; Y: interrupt 9 | ||
| 353 | jmp hw_int ; reflect it to virtual mode | ||
| 354 | vm_trap09 endp | ||
| 355 | |||
| 356 | ;****************************************************************************** | ||
| 357 | ; CPU: Invalid TSS fault | ||
| 358 | ; H/W: IRQ2 - Cascade from slave 8259 (see INT 70-77) | ||
| 359 | ; (shouldn't get H/W interrupts here) | ||
| 360 | ; | ||
| 361 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 362 | ; Error Code on stack = Selector | ||
| 363 | ; EXIT: to handler or debugger as appropriate | ||
| 364 | ; USED: | ||
| 365 | ; STACK: | ||
| 366 | |||
| 367 | ; to do: someone could reprogram master 8259 - need to handle ? | ||
| 368 | ;------------------------------------------------------------------------------ | ||
| 369 | vm_trap0A proc near | ||
| 370 | ProcessExcep ErrTSS | ||
| 371 | vm_trap0A endp | ||
| 372 | |||
| 373 | |||
| 374 | ;****************************************************************************** | ||
| 375 | ; CPU: Segment Not Present fault | ||
| 376 | ; H/W: IRQ3 - COM2 | ||
| 377 | ; | ||
| 378 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 379 | ; Error Code on stack = Selector | ||
| 380 | ; EXIT: to handler or debugger as appropriate | ||
| 381 | ; USED: | ||
| 382 | ; STACK: | ||
| 383 | ;------------------------------------------------------------------------------ | ||
| 384 | vm_trap0B proc near | ||
| 385 | PUSH_EBP | ||
| 386 | mov bp,sp | ||
| 387 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 388 | jz vmtB_dexit ; N: exit to debugger | ||
| 389 | push 000Bh ; Y: interrupt 0B | ||
| 390 | jmp hw_int ; reflect it to virtual mode | ||
| 391 | vmtB_dexit: | ||
| 392 | ProcessExcep ErrSegNP | ||
| 393 | vm_trap0B endp | ||
| 394 | |||
| 395 | ;****************************************************************************** | ||
| 396 | ; CPU: Stack fault | ||
| 397 | ; H/W: IRQ4 - COM1 | ||
| 398 | ; | ||
| 399 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 400 | ; Error Code on stack = Selector or 0000 | ||
| 401 | ; EXIT: to handler or debugger as appropriate | ||
| 402 | ; USED: | ||
| 403 | ; STACK: | ||
| 404 | ;------------------------------------------------------------------------------ | ||
| 405 | vm_trap0C proc near | ||
| 406 | PUSH_EBP | ||
| 407 | mov bp,sp | ||
| 408 | test [bp.VTFO+VMTF_EFLAGShi],2 ; Q: client in Virtual Mode ? | ||
| 409 | jz vmtC_dexit ; N: exit to debugger | ||
| 410 | push 000Ch ; Y: interrupt 0C | ||
| 411 | jmp hw_int ; reflect it to virtual mode | ||
| 412 | vmtC_dexit: | ||
| 413 | ProcessExcep ErrStack | ||
| 414 | vm_trap0C endp | ||
| 415 | |||
| 416 | ;****************************************************************************** | ||
| 417 | ; CPU: General Protection fault | ||
| 418 | ; H/W: IRQ5 - Second parallel printer | ||
| 419 | ; | ||
| 420 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 421 | ; Error Code on stack = Selector or 0000 | ||
| 422 | ; EXIT: to handler or debugger as appropriate | ||
| 423 | ; USED: | ||
| 424 | ; STACK: | ||
| 425 | ;------------------------------------------------------------------------------ | ||
| 426 | vm_trap0D proc near | ||
| 427 | PUSH_EBP | ||
| 428 | mov bp,sp | ||
| 429 | cmp sp,VMT_STACK ; Q: H/W interrupt from VM ? | ||
| 430 | jne vmtD_1 ; N: continue | ||
| 431 | push 000Dh ; Y: interrupt vector 0Dh | ||
| 432 | jmp hw_int ; reflect it to virtual mode | ||
| 433 | ; | ||
| 434 | ; Here we have a GP fault that was not a H/W interrupt 13 from VM. | ||
| 435 | ; | ||
| 436 | vmtD_1: | ||
| 437 | cmp sp,VMTERR_STACK ; Q: 'normal' exception w/error code ? | ||
| 438 | jne vmtD_dexit ; N: what the hell was it ???? - exit | ||
| 439 | jmp VmFault ; Y: enter VM GP fault handler | ||
| 440 | ; (fall thru to debugger) | ||
| 441 | vmtD_dexit: | ||
| 442 | ProcessExcep ErrGP | ||
| 443 | vm_trap0D endp | ||
| 444 | |||
| 445 | ;****************************************************************************** | ||
| 446 | ; CPU: Page fault | ||
| 447 | ; H/W: IRQ6 - diskette interrupt | ||
| 448 | ; | ||
| 449 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 450 | ; Error Code on stack = type of fault | ||
| 451 | ; EXIT: to handler or debugger as appropriate | ||
| 452 | ; USED: | ||
| 453 | ; STACK: | ||
| 454 | ;------------------------------------------------------------------------------ | ||
| 455 | vm_trap0E proc near | ||
| 456 | PUSH_EBP | ||
| 457 | mov bp,sp | ||
| 458 | cmp sp,VMT_STACK ; Q: H/W interrupt from VM ? | ||
| 459 | jne vmtE_dexit ; N: exit to debugger | ||
| 460 | push 000Eh ; Y: interrupt vector 0Eh | ||
| 461 | jmp hw_int ; reflect it to virtual mode | ||
| 462 | vmtE_dexit: | ||
| 463 | ProcessExcep ErrPage | ||
| 464 | vm_trap0E endp | ||
| 465 | |||
| 466 | ;****************************************************************************** | ||
| 467 | ; CPU: (none) | ||
| 468 | ; H/W: IRQ7 - parallel printer | ||
| 469 | ; | ||
| 470 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 471 | ; No error code on stack | ||
| 472 | ; EXIT: to handler or debugger as appropriate | ||
| 473 | ; USED: | ||
| 474 | ; STACK: | ||
| 475 | ;------------------------------------------------------------------------------ | ||
| 476 | vm_trap0F proc near | ||
| 477 | PUSH_EBP | ||
| 478 | mov bp,sp | ||
| 479 | push 000Fh ; push interrupt number | ||
| 480 | jmp hw_int ; enter common H/W interrupt handler | ||
| 481 | vm_trap0F endp | ||
| 482 | |||
| 483 | ;****************************************************************************** | ||
| 484 | ; CPU: Coprocessor Error - GOES TO NOT PRESENT FAULT IN DEBUGGER FOR NOW | ||
| 485 | ; | ||
| 486 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 487 | ; No error code on stack | ||
| 488 | ; EXIT: to handler or debugger as appropriate | ||
| 489 | ; USED: | ||
| 490 | ; STACK: | ||
| 491 | ;------------------------------------------------------------------------------ | ||
| 492 | vm_trap10 proc near | ||
| 493 | ProcessExcep ErrCoPerr | ||
| 494 | vm_trap10 endp | ||
| 495 | |||
| 496 | ;****************************************************************************** | ||
| 497 | ; VmTrap5x - Handlers for hardware interrupts. Sometimes the master 8259 | ||
| 498 | ; is set to here. | ||
| 499 | ; | ||
| 500 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 501 | ; EXIT: EBP pushed on stack | ||
| 502 | ; BP = normal stack frame pointer | ||
| 503 | ; Interrupt number pushed on stack | ||
| 504 | ; USED: | ||
| 505 | ; STACK: (4 bytes) | ||
| 506 | ;------------------------------------------------------------------------------ | ||
| 507 | vm_trap50 proc near | ||
| 508 | PUSH_EBP | ||
| 509 | mov bp,sp ; set up BP frame pointer | ||
| 510 | push 0050h | ||
| 511 | jmp short hw_int ; enter common code | ||
| 512 | vm_trap50 endp | ||
| 513 | |||
| 514 | ;------------------------------------------------------------------------------ | ||
| 515 | vm_trap51 proc near | ||
| 516 | PUSH_EBP | ||
| 517 | mov bp,sp ; set up BP frame pointer | ||
| 518 | push 0051h | ||
| 519 | jmp short hw_int ; enter common code | ||
| 520 | vm_trap51 endp | ||
| 521 | |||
| 522 | ;------------------------------------------------------------------------------ | ||
| 523 | vm_trap52 proc near | ||
| 524 | PUSH_EBP | ||
| 525 | mov bp,sp ; set up BP frame pointer | ||
| 526 | push 0052h | ||
| 527 | jmp short hw_int ; enter common code | ||
| 528 | vm_trap52 endp | ||
| 529 | |||
| 530 | ;------------------------------------------------------------------------------ | ||
| 531 | vm_trap53 proc near | ||
| 532 | PUSH_EBP | ||
| 533 | mov bp,sp ; set up BP frame pointer | ||
| 534 | push 0053h | ||
| 535 | jmp short hw_int ; enter common code | ||
| 536 | vm_trap53 endp | ||
| 537 | |||
| 538 | ;------------------------------------------------------------------------------ | ||
| 539 | vm_trap54 proc near | ||
| 540 | PUSH_EBP | ||
| 541 | mov bp,sp ; set up BP frame pointer | ||
| 542 | push 0054h | ||
| 543 | jmp short hw_int ; enter common code | ||
| 544 | vm_trap54 endp | ||
| 545 | |||
| 546 | ;------------------------------------------------------------------------------ | ||
| 547 | vm_trap55 proc near | ||
| 548 | PUSH_EBP | ||
| 549 | mov bp,sp ; set up BP frame pointer | ||
| 550 | push 0055h | ||
| 551 | jmp short hw_int ; enter common code | ||
| 552 | vm_trap55 endp | ||
| 553 | |||
| 554 | ;------------------------------------------------------------------------------ | ||
| 555 | vm_trap56 proc near | ||
| 556 | PUSH_EBP | ||
| 557 | mov bp,sp ; set up BP frame pointer | ||
| 558 | push 0056h | ||
| 559 | jmp short hw_int ; enter common code | ||
| 560 | vm_trap56 endp | ||
| 561 | |||
| 562 | ;------------------------------------------------------------------------------ | ||
| 563 | vm_trap57 proc near | ||
| 564 | PUSH_EBP | ||
| 565 | mov bp,sp ; set up BP frame pointer | ||
| 566 | push 0057h | ||
| 567 | jmp short hw_int ; enter common code | ||
| 568 | vm_trap57 endp | ||
| 569 | |||
| 570 | ;****************************************************************************** | ||
| 571 | ; VmTrap7x - handlers for hardware interrupts from the slave 8259 | ||
| 572 | ; | ||
| 573 | ; ENTRY: 386 Protected Mode via 386 Interrupt gate | ||
| 574 | ; EXIT: EBP pushed on stack | ||
| 575 | ; BP = normal stack frame pointer | ||
| 576 | ; Interrupt number pushed on stack | ||
| 577 | ; USED: | ||
| 578 | ; STACK: (4 bytes) | ||
| 579 | ;------------------------------------------------------------------------------ | ||
| 580 | vm_trap70 proc near | ||
| 581 | PUSH_EBP | ||
| 582 | mov bp,sp ; set up BP frame pointer | ||
| 583 | push 0070h | ||
| 584 | jmp short hw_int ; enter common code | ||
| 585 | vm_trap70 endp | ||
| 586 | |||
| 587 | ;------------------------------------------------------------------------------ | ||
| 588 | vm_trap71 proc near | ||
| 589 | PUSH_EBP | ||
| 590 | mov bp,sp ; set up BP frame pointer | ||
| 591 | push 0071h | ||
| 592 | jmp short hw_int ; enter common code | ||
| 593 | vm_trap71 endp | ||
| 594 | |||
| 595 | ;------------------------------------------------------------------------------ | ||
| 596 | vm_trap72 proc near | ||
| 597 | PUSH_EBP | ||
| 598 | mov bp,sp ; set up BP frame pointer | ||
| 599 | push 0072h | ||
| 600 | jmp short hw_int ; enter common code | ||
| 601 | vm_trap72 endp | ||
| 602 | |||
| 603 | ;------------------------------------------------------------------------------ | ||
| 604 | vm_trap73 proc near | ||
| 605 | PUSH_EBP | ||
| 606 | mov bp,sp ; set up BP frame pointer | ||
| 607 | push 0073h | ||
| 608 | jmp short hw_int ; enter common code | ||
| 609 | vm_trap73 endp | ||
| 610 | |||
| 611 | ;------------------------------------------------------------------------------ | ||
| 612 | vm_trap74 proc near | ||
| 613 | PUSH_EBP | ||
| 614 | mov bp,sp ; set up BP frame pointer | ||
| 615 | push 0074h | ||
| 616 | jmp short hw_int ; enter common code | ||
| 617 | vm_trap74 endp | ||
| 618 | |||
| 619 | ;------------------------------------------------------------------------------ | ||
| 620 | vm_trap75 proc near | ||
| 621 | PUSH_EBP | ||
| 622 | mov bp,sp ; set up BP frame pointer | ||
| 623 | push 0075h | ||
| 624 | jmp short hw_int ; enter common code | ||
| 625 | vm_trap75 endp | ||
| 626 | |||
| 627 | ;------------------------------------------------------------------------------ | ||
| 628 | vm_trap76 proc near | ||
| 629 | PUSH_EBP | ||
| 630 | mov bp,sp ; set up BP frame pointer | ||
| 631 | push 0076h | ||
| 632 | jmp short hw_int ; enter common code | ||
| 633 | vm_trap76 endp | ||
| 634 | |||
| 635 | ;------------------------------------------------------------------------------ | ||
| 636 | vm_trap77 proc near | ||
| 637 | PUSH_EBP | ||
| 638 | mov bp,sp ; set up BP frame pointer | ||
| 639 | push 0077h | ||
| 640 | jmp short hw_int ; enter common code | ||
| 641 | vm_trap77 endp | ||
| 642 | |||
| 643 | page | ||
| 644 | ;****************************************************************************** | ||
| 645 | ; HW_INT - common handler for hardware interrupts. The interrupt is | ||
| 646 | ; reflected directly to the appropriate Real Mode (Virtual) handler. | ||
| 647 | ; This entry point clear the trace flag (TF) and int flag (IF), since | ||
| 648 | ; a h/w interrupt would (NOTE: INT n and INTO instructions also clear | ||
| 649 | ; TF and IF - so this entry is suitable for reflecting these also). | ||
| 650 | ; | ||
| 651 | ; EMUL_REFLECT - entry point for reflecting emulations. | ||
| 652 | ; This entry point does not clear the trace flag (TF) and int flag (IF). | ||
| 653 | ; | ||
| 654 | ; 386 interrupt gate switched us to the Ring 0 stack on the way in | ||
| 655 | ; from Virtual Mode and pushed 32-bit values as follows: | ||
| 656 | ; | ||
| 657 | ; hiword loword offset (in addition to EBP push) | ||
| 658 | ; +------+------+ <-------- Top of 'kernel' stack | ||
| 659 | ; | 0000 | GS | +32 (decimal) | ||
| 660 | ; |------|------| | ||
| 661 | ; | 0000 | FS | +28 | ||
| 662 | ; |------|------| | ||
| 663 | ; | 0000 | DS | +24 | ||
| 664 | ; |------|------| | ||
| 665 | ; | 0000 | ES | +20 | ||
| 666 | ; |------|------| | ||
| 667 | ; | 0000 | SS | +16 | ||
| 668 | ; |------|------| | ||
| 669 | ; | ESP | +12 | ||
| 670 | ; |------|------| | ||
| 671 | ; | EFLAGS | +08 | ||
| 672 | ; |------|------| | ||
| 673 | ; | 0000 | CS | +04 | ||
| 674 | ; |------|------| | ||
| 675 | ; | EIP | +00 | ||
| 676 | ; +------+------+ <-------- Ring 0 SS:SP | ||
| 677 | ; | (ebp) | | ||
| 678 | ; +-------------+ <-------- Ring 0 SS:BP | ||
| 679 | ; | ||
| 680 | ; The object of this routine is to massage the trap stack frame (above) | ||
| 681 | ; and build a 'real mode' stack frame for the virtual mode client so that | ||
| 682 | ; we can transfer control to virtual mode at the address specified in | ||
| 683 | ; the appropriate real mode IDT vector. The client's IRET out of the | ||
| 684 | ; interrupt routine will proceed normally (assuming we're letting him | ||
| 685 | ; run with IOPL = 3). Since we're fielding the trap from Virtual Mode, | ||
| 686 | ; we assume the high word of ESP and EIP is 0000. | ||
| 687 | ; | ||
| 688 | ; +-------+ <-------- Client's current SS:SP | ||
| 689 | ; | Flags | +4 | ||
| 690 | ; |-------| | ||
| 691 | ; | CS | +2 | ||
| 692 | ; |-------| | ||
| 693 | ; | IP | +0 | ||
| 694 | ; +-------+ <-------- Client's SS:SP when we let him have control | ||
| 695 | ; | ||
| 696 | ; Assume entry from Virtual Mode, for now. We shouldn't be getting entered | ||
| 697 | ; here except via Hardware interrupt, so no sanity checks are performed. | ||
| 698 | ; | ||
| 699 | ; ENTRY: 386 Protected Mode | ||
| 700 | ; BP -> standard frame | ||
| 701 | ; EBP and Interrupt number have been pushed onto stack | ||
| 702 | ; EXIT: via IRET to VM86 program | ||
| 703 | ; appropriate real mode IRET set up @ client's SS:SP | ||
| 704 | ; USED: (none) (note that DS & ES are free to use - saved during trap) | ||
| 705 | ; STACK: | ||
| 706 | ; | ||
| 707 | ; to do: Need to check for entry mode ? | ||
| 708 | ;------------------------------------------------------------------------------ | ||
| 709 | hw_int proc near | ||
| 710 | push bx | ||
| 711 | push si ; | ||
| 712 | mov si,[bp.VTFO+VMTF_EFLAGS] ; SI = saved low word of EFLAGS | ||
| 713 | ; | ||
| 714 | ; *** clear IF bit and Trace Flag on flags for reflect, but leave them | ||
| 715 | ; unchanged for the flags on the IRET stack we build on the | ||
| 716 | ; client's stack. | ||
| 717 | ; | ||
| 718 | and [bp.VTFO+VMTF_EFLAGS],not 300h ; clear IF and TF | ||
| 719 | reflect_common: | ||
| 720 | ; | ||
| 721 | ; Build a selector (VM1_GSEL) to client's stack. VM1_GSEL is already set | ||
| 722 | ; up with limit (0FFFFh) and access (D_DATA0), so just fill in the base. | ||
| 723 | ; | ||
| 724 | HwTabUnlock ; disable HW protection on high ram | ||
| 725 | mov bx,GDTD_GSEL ; get GDT data alias | ||
| 726 | mov ds,bx ; DS -> GDT | ||
| 727 | mov bx,[bp.VTFO+VMTF_SS] ; BX = VM SS (segment form) | ||
| 728 | shl bx,4 ; BX = low 16 bits of base | ||
| 729 | mov ds:[VM1_GSEL+2],bx ; place in descriptor | ||
| 730 | mov bx,[bp.VTFO+VMTF_SS] ; BX = VM SS (again) | ||
| 731 | shr bx,4 ; BH = high 8 bits of base | ||
| 732 | mov ds:[VM1_GSEL+4],bh ; place in descriptor | ||
| 733 | ; | ||
| 734 | ; Adjust client's SP to make room for building his IRET frame | ||
| 735 | ; | ||
| 736 | sub word ptr [bp.VTFO+VMTF_ESP],6 ; adjust client's SP | ||
| 737 | mov bx, VM1_GSEL | ||
| 738 | mov ds, bx ; DS = VM stack segment | ||
| 739 | ; | ||
| 740 | mov bx,si ; BX = low word of client's EFLAGS | ||
| 741 | ; | ||
| 742 | mov si,[bp.VTFO+VMTF_ESP] ; DS:SI = pointer to client's frame | ||
| 743 | ; | ||
| 744 | ; Move low 16 bits of Flags, CS, and EIP from IRET frame to client stack frame | ||
| 745 | ; | ||
| 746 | mov ds:[si.4],bx ; to client's flags | ||
| 747 | mov bx,[bp.VTFO+VMTF_CS] ; | ||
| 748 | mov ds:[si.2],bx ; to client's CS | ||
| 749 | mov bx,[bp.VTFO+VMTF_EIP] ; low word of EIP | ||
| 750 | mov ds:[si.0],bx ; to client's IP | ||
| 751 | ; | ||
| 752 | ; Replace low 16 bits of IRET frame CS:EIP with vector from real mode IDT | ||
| 753 | ; | ||
| 754 | mov bx,[bp-2] ; get the interrupt vector | ||
| 755 | shl bx,2 ; BX = BX * 4 (vector table index) | ||
| 756 | mov si,RM_IDT_GSEL ; get real mode IDT alias | ||
| 757 | mov ds,si ; DS -> Real Mode IDT | ||
| 758 | mov si,ds:[bx] ; | ||
| 759 | mov [bp.VTFO+VMTF_EIP],si ; move the IP | ||
| 760 | mov si,ds:[bx+2] ; | ||
| 761 | mov [bp.VTFO+VMTF_CS],si ; move the CS | ||
| 762 | ; | ||
| 763 | ; 32-bit IRET back to client | ||
| 764 | ; | ||
| 765 | HwTabLock ; enable HW protection on high ram | ||
| 766 | pop si ; restore local regs | ||
| 767 | pop bx | ||
| 768 | pop bp ; throw away fake interrupt number | ||
| 769 | POP_EBP | ||
| 770 | db 66h | ||
| 771 | iret ; *** RETURN *** to client | ||
| 772 | hw_int endp | ||
| 773 | |||
| 774 | ;****************************************************************************** | ||
| 775 | ; EMUL_REFLECT | ||
| 776 | ;****************************************************************************** | ||
| 777 | ; | ||
| 778 | ; emulation relfection entry point - don't mess with client's flags | ||
| 779 | ; | ||
| 780 | emul_reflect label near | ||
| 781 | push bx ; local registers | ||
| 782 | push si ; | ||
| 783 | mov si,[bp.VTFO+VMTF_EFLAGS] ; SI = saved low word of EFLAGS | ||
| 784 | jmp reflect_common | ||
| 785 | |||
| 786 | |||
| 787 | ; | ||
| 788 | _TEXT ends ; end of segment | ||
| 789 | ; | ||
| 790 | end ; end of module | ||
| 791 | \ No newline at end of file | ||