source: vendor/emx/0.9d-fix04/src/dos/pmint.asm

Last change on this file was 18, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 99.8 KB
Line 
1;
2; PMINT.ASM -- Handle interrupts
3;
4; Copyright (c) 1991-1996 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26;
27; Handle interrupts in protected mode (hardware and software interrupts).
28; Includes DOS interface.
29;
30
31__PMINT = 1
32 INCLUDE EMX.INC
33 INCLUDE TABLES.INC
34 INCLUDE VPRINT.INC
35 INCLUDE OPRINT.INC
36 INCLUDE PAGING.INC
37 INCLUDE SYSCALL.INC
38 INCLUDE EXTAPI.INC
39 INCLUDE SIGNAL.INC
40 INCLUDE PROCESS.INC
41 INCLUDE PROFIL.INC
42 INCLUDE VCPI.INC
43 INCLUDE PMINT.INC
44 INCLUDE EXCEPT.INC
45 INCLUDE RPRINT.INC
46 INCLUDE A20.INC
47 INCLUDE DEBUG.INC
48 INCLUDE SEGMENTS.INC
49 INCLUDE OPTIONS.INC
50 INCLUDE MISC.INC
51 INCLUDE CORE.INC
52 INCLUDE RMINT.INC
53 INCLUDE FILEIO.INC
54 INCLUDE UTILS.INC
55 INCLUDE TERMIO.INC
56 INCLUDE STAT.INC
57 INCLUDE ERRORS.INC
58
59 PUBLIC IRQ0_ADD, IRQ8_ADD
60 PUBLIC INTERRUPT, PMINT_21H, PMINT_10H, PMINT_11H
61 PUBLIC PMINT_14H, PMINT_16H, PMINT_17H, PMINT_31H, PMINT_33H
62 PUBLIC DOSF_ERROR, BREAK_AFTER_IRET, NMI, INT_RM
63 PUBLIC BUF_SEG, BUF1_SEG, BUF2_SEG, BUF_SEL, RM_CR0, PM_CR0
64 PUBLIC V2P_CONT, V2V_CONT, INIT_BUFFER
65 PUBLIC PMINT0_TAB, PMINT8_TAB, DBCS_LEAD_TAB
66 PUBLIC DOS_INT ; put into map file for debugging
67
68SER_FLAG = FALSE ; Don't use serial interface
69DEBUG_DOSDUMP = FALSE
70
71SV_DATA SEGMENT
72
73PMINT0_TAB LABEL WORD
74 IRP X,<0,1,2,3,4,5,6,7>
75 WORD OFFSET SV_CODE:PMINT&X
76 ENDM
77PMINT8_TAB LABEL WORD
78 IRP X,<8,9,10,11,12,13,14,15>
79 WORD OFFSET SV_CODE:PMINT&X
80 ENDM
81
82PMHWINT_LSS LABEL FWORD
83PMHWINT_ESP DWORD ?
84PMHWINT_SS WORD ?
85;
86; This variable points to the interrupt stack frame of protected mode
87; (in the protected-mode stack SV_STACK). It is used for accessing the
88; stack frame in real mode. Be sure to save this variable when passing
89; signals from real mode to protected mode!
90;
91FRAME_PTR WORD ?
92
93;
94; Before switching back to real/virtual mode, we restore the floating point
95; related bits of CR0 saved at the beginning. We can save the bits only
96; in protected mode, as CR0 isn't readable in virtual mode. After switching
97; to protected mode, we restore the floating point related bits of CR0
98; from PM_CR0.
99;
100 DALIGN 4
101RM_CR0 DWORD ? ; Real-mode CR0 (AND CR0_FPU)
102PM_CR0 DWORD ? ; Prot-mode CR0 (AND CR0_FPU)
103
104;
105; Table of conversions
106;
107
108DF_INVALID = 00H ; syscall function not supported
109DF_NULL = 01H ; No parameters to be converted
110DF_WRITE = 02H ; Input: src=DS:EDX, length=ECX -> DS:DX, CX
111DF_PATH = 03H ; Input: pathname=DS:EDX -> DS:DX
112DF_TEXT = 04H ; Input: text=DS:EDX ($ terminated) -> DS:DX
113DF_READ = 05H ; Output: dst=DS:DX, length=AX (CY=0 only) -> DS:EDX
114DF_SEEK = 06H ; Input: EDX -> CX:DX; output: DX:AX -> EAX (CY=0)
115DF_TMP = 07H ; Input/output: DS:DX (0 term.) + 13 bytes
116DF_INPUT = 08H ; Input/output: DS:DX, length=DX[0]+2
117DF_MOVE = 09H ; Input: DS:EDX -> DS:DX, DS:EDI -> ES:DI file names
118DF_DUP2 = 0AH ; Force duplicate file handle
119DF_CLOSE = 0BH ; Close file handle
120DF_IOCTL = 0CH ; IOCTL, use additional table
121DF_GETCWD = 0DH ; Output: DS:SI -> DS:ESI (64 bytes)
122DF_EXIT = 0EH ; Exit
123DF_FFIRST = 0FH ; Find first (DS:EDX, DTA DS:ESI)
124DF_FNEXT = 10H ; Find next (DTA DS:ESI)
125DF_VERSION = 11H ; Return DOS version (and emx)
126DF_EXEC = 12H ; Load and execute program
127DF_RETCODE = 13H ; Get return code of child process
128DF_STR_BP = 14H ; Input: EBP null-terminated string -> ES:BP
129DF_VESA = 15H ; VESA BIOS (10H, AH=4FH), use additional table
130DF_VESAINFO = 16H ; VESA function 00H (return 256 bytes)
131DF_VESAMODE = 17H ; VESA function 01H (return 256 bytes)
132DF_MOU_GCURSOR = 18H ; Mouse function 09H (in: ES:DX -> 64 bytes)
133DF_MOU_LGCURSOR = 19H ; Mouse function 12H (in: ES:DX -> var. bytes)
134DF_COUNTRY = 1AH ; Output: EDX->DS:DX (34 bytes) unless DX=-1
135DF_LOCK = 1BH ; Input: EDX->CX:DX, EDI->SI:DI
136DF_TRUENAME = 1CH ; DOS function 60H
137DF_PATH_SI = 1DH ; Input: pathname=DS:ESI -> DS:SI
138DF_DUP = 1EH ; Duplicate file handle
139DF_VIO11 = 1FH ; INT 10H AH=11H, use additional table (AL)
140DF_VIO12 = 20H ; INT 10H AH=12H, use additional table (BL)
141DF_LAST = 20H
142DF_SPARSE_END = 0FFH ; End of sparse table
143
144;
145; The following flag bits are used for INT 21H only. They also apply
146; to the INT 21H IOCTL calls.
147;
148DFE = 8000H ; CY indicates error, convert to errno
149DFM_STDIN = 4000H ; Map stdin before invoking INT 21H
150DFM_STDOUT = 2000H ; Map stdout before invoking INT 21H
151DFM_STDIO = DFM_STDIN OR DFM_STDOUT
152
153DFH_IN = 0100H ; BX contains file handle (in)
154DFH_OUT = 0200H ; New file handle returned in EAX (out, CY=0)
155DFH_IN_OUT = DFH_IN OR DFH_OUT
156
157;
158; Get conversion flag from a table
159;
160; In: BL Function number
161;
162; Out: AX Conversion flag
163; BX Modified
164;
165TBGET MACRO TABLE
166 TABLE&_GET
167 ENDM
168
169;
170; Start a dense table
171;
172; In: TABLE Name of the table
173; MAXFUN Highest function number
174;
175DENSE_TABLE MACRO TABLE, MAXFUN
176TABLE LABEL WORD
177DENSE_NEXT = 0
178DENSE_MAXFUN = MAXFUN
179TBENTRY MACRO FUNC, FLAG
180 DENSE_ENTRY FUNC, FLAG
181 ENDM
182TBEND MACRO
183 DENSE_END
184 ENDM
185TABLE&_MAXFUN = MAXFUN
186TABLE&_GET MACRO
187 DENSE_GET TABLE
188 ENDM
189 ENDM
190
191;
192; Add an entry to a dense table
193;
194DENSE_ENTRY MACRO FUNC, FLAG
195 .ERRE FUNC GE DENSE_NEXT
196 IF FUNC NE DENSE_NEXT
197 WORD FUNC-DENSE_NEXT DUP (DF_INVALID)
198DENSE_NEXT = FUNC
199 ENDIF
200 WORD FLAG
201DENSE_NEXT = DENSE_NEXT+1
202 ENDM
203
204;
205; End a dense table
206;
207DENSE_END MACRO
208 IF DENSE_NEXT NE DENSE_MAXFUN + 1
209 DENSE_ENTRY DENSE_MAXFUN, <DF_INVALID>
210 ENDIF
211 ENDM
212
213;
214; Get conversion flag from a dense table
215;
216; In: BL Function number
217;
218; Out: AX Conversion flag
219; BX Modified
220;
221DENSE_GET MACRO TABLE
222 IF TABLE&_MAXFUN NE 0FFH
223 CMP BL, TABLE&_MAXFUN
224 JA D_INVALID
225 ENDIF
226 XOR BH, BH
227 SHL BX, 1
228 MOV AX, TABLE[BX]
229 ENDM
230
231;
232; Start a sparse table
233;
234; In: TABLE Name of the table
235;
236SPARSE_TABLE MACRO TABLE
237TABLE LABEL BYTE
238TBENTRY MACRO FUNC, FLAG
239 SPARSE_ENTRY FUNC, FLAG
240 ENDM
241TBEND MACRO
242 SPARSE_END
243 ENDM
244TABLE&_GET MACRO
245 SPARSE_GET TABLE
246 ENDM
247 ENDM
248
249;
250; Add an entry to a sparse table
251;
252SPARSE_ENTRY MACRO FUNC, FLAG
253 BYTE FUNC
254 WORD FLAG
255 ENDM
256
257;
258; End a sparse table
259;
260SPARSE_END MACRO
261 SPARSE_ENTRY 00H, DF_SPARSE_END
262 ENDM
263
264;
265; Get conversion flag from a sparse table
266;
267; In: BL Function number
268;
269; Out: AX Conversion flag
270; BX Modified
271;
272SPARSE_GET MACRO TABLE
273 LOCAL LOOP1, DONE
274 MOV AL, BL
275 LEA BX, TABLE - 3
276LOOP1: ADD BX, 3
277 CMP BYTE PTR [BX+1], DF_SPARSE_END
278 JE D_INVALID
279 CMP [BX+0], AL
280 JNE LOOP1
281 MOV AX, [BX+1]
282 ENDM
283
284
285 DENSE_TABLE DOS_FUNCS, 6CH
286 TBENTRY 01H, <DF_NULL OR DFM_STDIO> ; Read keyboard and echo
287 TBENTRY 02H, <DF_NULL OR DFM_STDOUT> ; Display character
288 TBENTRY 03H, <DF_NULL> ; Auxiliary input
289 TBENTRY 04H, <DF_NULL> ; Auxiliary output
290 TBENTRY 05H, <DF_NULL> ; Print character
291 TBENTRY 06H, <DF_NULL OR DFM_STDIO> ; Direct console i/o
292 TBENTRY 07H, <DF_NULL OR DFM_STDIN> ; Direct console input
293 TBENTRY 08H, <DF_NULL OR DFM_STDIN> ; Read keyboard
294 TBENTRY 09H, <DF_TEXT OR DFM_STDOUT> ; Display string
295 TBENTRY 0AH, <DF_INPUT OR DFM_STDIO> ; Buffered keyboard input
296 TBENTRY 0BH, <DF_NULL OR DFM_STDIN> ; Check keyboard status
297 TBENTRY 0CH, <DF_NULL OR DFM_STDIO> ; Flush keyboard buffer
298 TBENTRY 0DH, <DF_NULL> ; Reset disk
299 TBENTRY 0EH, <DF_NULL> ; Select disk
300 TBENTRY 19H, <DF_NULL> ; Get current disk
301 TBENTRY 2AH, <DF_NULL> ; Get date
302 TBENTRY 2BH, <DF_NULL> ; Set date
303 TBENTRY 2CH, <DF_NULL> ; Get time
304 TBENTRY 2DH, <DF_NULL> ; Set time
305 TBENTRY 2EH, <DF_NULL> ; Set/reset verify flag
306 TBENTRY 30H, <DF_VERSION> ; Get DOS version number
307 TBENTRY 33H, <DF_NULL> ; Control-C check
308 TBENTRY 36H, <DF_NULL> ; Get disk free space
309 TBENTRY 37H, <DF_NULL> ; Get/set switch character
310 TBENTRY 38H, <DFE OR DF_COUNTRY> ; Get/set country data
311 TBENTRY 39H, <DFE OR DF_PATH> ; Create directory
312 TBENTRY 3AH, <DFE OR DF_PATH> ; Remove directory
313 TBENTRY 3BH, <DFE OR DF_PATH> ; Change current directory
314 TBENTRY 3CH, <DFE OR DF_PATH OR DFH_OUT> ; Create handle
315 TBENTRY 3DH, <DFE OR DF_PATH OR DFH_OUT> ; Open handle
316 TBENTRY 3EH, <DFE OR DF_CLOSE> ; Close handle
317 TBENTRY 3FH, <DFE OR DF_READ OR DFH_IN> ; Read handle
318 TBENTRY 40H, <DFE OR DF_WRITE OR DFH_IN> ; Write handle
319 TBENTRY 41H, <DFE OR DF_PATH> ; Delete directory entry
320 TBENTRY 42H, <DFE OR DF_SEEK OR DFH_IN> ; Move file pointer
321 TBENTRY 43H, <DFE OR DF_PATH> ; Get/set file attributes
322 TBENTRY 44H, <DF_IOCTL> ; IOCTL
323 TBENTRY 45H, <DF_DUP> ; Duplicate file handle
324 TBENTRY 46H, <DF_DUP2> ; Force duplicate handle
325 TBENTRY 47H, <DFE OR DF_GETCWD> ; Get current directory
326 TBENTRY 4BH, <DFE OR DF_EXEC> ; Load and execute program
327 TBENTRY 4CH, <DF_EXIT> ; End process
328 TBENTRY 4DH, <DF_RETCODE> ; Get rc of child process
329 TBENTRY 4EH, <DFE OR DF_FFIRST> ; Find first file
330 TBENTRY 4FH, <DFE OR DF_FNEXT> ; Find next file
331 TBENTRY 54H, <DF_NULL> ; Get verify state
332 TBENTRY 56H, <DFE OR DF_MOVE> ; Change directory entry
333 TBENTRY 57H, <DFE OR DF_NULL OR DFH_IN> ; Time/date of file
334 TBENTRY 58H, <DFE OR DF_NULL> ; Get/set alloc strat
335 TBENTRY 59H, <DF_NULL> ; Get extended error
336 TBENTRY 5AH, <DFE OR DF_TMP OR DFH_OUT> ; Create temporary file
337 TBENTRY 5BH, <DFE OR DF_PATH OR DFH_OUT> ; Create new file
338 TBENTRY 5CH, <DFE OR DF_LOCK OR DFH_IN> ; Lock
339 TBENTRY 60H, <DFE OR DF_TRUENAME> ; Canonicalize path
340 TBENTRY 66H, <DFE OR DF_NULL> ; Get/set global cp table
341 TBENTRY 67H, <DFE OR DF_NULL> ; Set handle count
342 TBENTRY 68H, <DFE OR DF_NULL OR DFH_IN> ; Commit file
343 TBENTRY 6AH, <DFE OR DF_NULL OR DFH_IN> ; Commit file
344 TBENTRY 6CH, <DFE OR DF_PATH_SI OR DFH_OUT> ; Extended open/create
345 TBEND
346
347 DENSE_TABLE IOCTL_FUNCS, 0BH
348 TBENTRY 00H, <DFE OR DF_NULL OR DFH_IN> ; Get device data
349 TBENTRY 01H, <DFE OR DF_NULL OR DFH_IN> ; Set device data
350 TBENTRY 02H, <DFE OR DF_WRITE OR DFH_IN> ; Send control data (char)
351 TBENTRY 03H, <DFE OR DF_READ OR DFH_IN> ; Receive ctl data (char)
352 TBENTRY 04H, <DFE OR DF_WRITE> ; Send ctl data (block)
353 TBENTRY 05H, <DFE OR DF_READ> ; Receive ctl data (block)
354 TBENTRY 06H, <DFE OR DF_NULL OR DFH_IN> ; Check input status
355 TBENTRY 07H, <DFE OR DF_NULL OR DFH_IN> ; Check output status
356 TBENTRY 08H, <DFE OR DF_NULL> ; Is changable
357 TBENTRY 09H, <DFE OR DF_NULL> ; Is redirected block
358 TBENTRY 0AH, <DFE OR DF_NULL OR DFH_IN> ; Is redirected handle
359 TBENTRY 0BH, <DFE OR DF_NULL> ; Retry
360 TBEND
361
362 DENSE_TABLE VIO_FUNCS, 0FFH
363 TBENTRY 00H, <DF_NULL> ; Set video mode
364 TBENTRY 01H, <DF_NULL> ; Set cursor shape
365 TBENTRY 02H, <DF_NULL> ; Set cursor position
366 TBENTRY 03H, <DF_NULL> ; Set cursor pos and size
367 TBENTRY 04H, <DF_NULL> ; Read light pen position
368 TBENTRY 05H, <DF_NULL> ; Select display page
369 TBENTRY 06H, <DF_NULL> ; Scroll up
370 TBENTRY 07H, <DF_NULL> ; Scroll down
371 TBENTRY 08H, <DF_NULL> ; Read char and attribute
372 TBENTRY 09H, <DF_NULL> ; Write char and attribute
373 TBENTRY 0AH, <DF_NULL> ; Write character
374 TBENTRY 0BH, <DF_NULL> ; Set palette
375 TBENTRY 0CH, <DF_NULL> ; Write graphics pixel
376 TBENTRY 0DH, <DF_NULL> ; Read graphics pixel
377 TBENTRY 0EH, <DF_NULL> ; Teletype output
378 TBENTRY 0FH, <DF_NULL> ; Get current video mode
379 TBENTRY 10H, <DF_NULL> ; Palette (AL != 02H,
380 ; 09H, 12H, 17H)
381 TBENTRY 11H, <DF_VIO11> ; Font
382 TBENTRY 12H, <DF_VIO12> ; Miscellaneous stuff
383 TBENTRY 13H, <DF_STR_BP> ; Write string
384 TBENTRY 14H, <DF_INVALID> ; LCD
385 TBENTRY 15H, <DF_INVALID> ; Get parameters
386 TBENTRY 1AH, <DF_NULL> ; Display combination
387 TBENTRY 1BH, <DF_INVALID> ; State information
388 TBENTRY 1CH, <DF_INVALID> ; Save/restore state
389 TBENTRY 1FH, <DF_INVALID> ; XGA DMQS
390 TBENTRY 30H, <DF_INVALID> ; 3270 stuff
391 TBENTRY 40H, <DF_NULL> ; Hercules GRAFIX
392 TBENTRY 41H, <DF_NULL> ; Hercules GRAFIX
393 TBENTRY 42H, <DF_NULL> ; Hercules GRAFIX
394 TBENTRY 43H, <DF_NULL> ; Hercules GRAFIX
395 TBENTRY 44H, <DF_NULL> ; Hercules GRAFIX
396 TBENTRY 45H, <DF_NULL> ; Hercules GRAFIX
397 TBENTRY 46H, <DF_NULL> ; Hercules GRAFIX
398 TBENTRY 47H, <DF_NULL> ; Hercules GRAFIX
399 TBENTRY 48H, <DF_NULL> ; Hercules GRAFIX
400 TBENTRY 49H, <DF_NULL> ; Hercules GRAFIX
401 TBENTRY 4AH, <DF_NULL> ; Hercules GRAFIX
402 TBENTRY 4BH, <DF_NULL> ; Hercules GRAFIX / FRIEZE
403 TBENTRY 4CH, <DF_NULL> ; Hercules GRAFIX
404 TBENTRY 4DH, <DF_NULL> ; Hercules GRAFIX
405 TBENTRY 4EH, <DF_NULL> ; Hercules GRAFIX
406 TBENTRY 4FH, <DF_VESA> ; VESA
407 TBENTRY 6FH, <DF_NULL> ; Various functions
408 TBENTRY 0F0H, <DF_NULL> ; EGA register interface
409 TBENTRY 0F1H, <DF_NULL> ; EGA register interface
410 TBENTRY 0F6H, <DF_NULL> ; EGA register interface
411 TBEND
412
413 DENSE_TABLE VESA_FUNCS, 08H
414 TBENTRY 00H, <DF_VESAINFO> ; Get SVGA info
415 TBENTRY 01H, <DF_VESAMODE> ; Get SVGA mode info
416 TBENTRY 02H, <DF_NULL> ; Set mode
417 TBENTRY 03H, <DF_NULL> ; Get mode
418 TBENTRY 04H, <DF_INVALID> ; Save/restore state
419 TBENTRY 05H, <DF_NULL> ; Memory control
420 TBENTRY 06H, <DF_NULL> ; Scan line length
421 TBENTRY 07H, <DF_NULL> ; Display start
422 TBENTRY 08H, <DF_NULL> ; DAC palette control
423 TBEND
424
425 DENSE_TABLE VIO11_FUNCS, 24H
426 TBENTRY 01H, <DF_NULL> ; Load ROM patterns 8x14
427 TBENTRY 02H, <DF_NULL> ; Load ROM patterns 8x8
428 TBENTRY 03H, <DF_NULL> ; Set block specifier
429 TBENTRY 04H, <DF_NULL> ; Load ROM charset 8x14
430 TBENTRY 11H, <DF_NULL> ; Load ROM patterns 8x14
431 TBENTRY 12H, <DF_NULL> ; Load ROM patterns 8x8
432 TBENTRY 14H, <DF_NULL> ; Load ROM charset 8x14
433 TBENTRY 22H, <DF_NULL> ; Set ROM graph chars 8x14
434 TBENTRY 23H, <DF_NULL> ; Set ROM graph chars 8x8
435 TBENTRY 24H, <DF_NULL> ; Set ROM graph chars 8x16
436 TBEND
437
438 SPARSE_TABLE VIO12_FUNCS
439 TBENTRY 10H, <DF_NULL> ; Get EGA info
440 TBENTRY 20H, <DF_NULL> ; Alternate PrtSc
441 TBENTRY 30H, <DF_NULL> ; Select vert. resolution
442 TBENTRY 31H, <DF_NULL> ; Palette loading
443 TBENTRY 32H, <DF_NULL> ; Video addressing
444 TBENTRY 33H, <DF_NULL> ; Gray-scale summing
445 TBENTRY 34H, <DF_NULL> ; Cursor emulation
446 TBENTRY 36H, <DF_NULL> ; Video refresh control
447 TBENTRY 37H, <DF_NULL> ; Mainframe interact. sup
448 TBEND
449
450 DENSE_TABLE MOU_FUNCS, 6DH
451 TBENTRY 00H, <DF_NULL> ; Reset
452 TBENTRY 01H, <DF_NULL> ; Show mouse cursor
453 TBENTRY 02H, <DF_NULL> ; Hide mouse cursor
454 TBENTRY 03H, <DF_NULL> ; Get position & status
455 TBENTRY 04H, <DF_NULL> ; Position mouse cursor
456 TBENTRY 05H, <DF_NULL> ; Get button down data
457 TBENTRY 06H, <DF_NULL> ; Get button up data
458 TBENTRY 07H, <DF_NULL> ; Define hor. range
459 TBENTRY 08H, <DF_NULL> ; Define ver. range
460 TBENTRY 09H, <DF_MOU_GCURSOR> ; Define graphics cursor
461 TBENTRY 0AH, <DF_NULL> ; Define text cursor
462 TBENTRY 0BH, <DF_NULL> ; Read motion counters
463 TBENTRY 0CH, <DF_INVALID> ; Define IRQ routine
464 TBENTRY 0DH, <DF_NULL> ; Light pen emulation on
465 TBENTRY 0EH, <DF_NULL> ; Light pen emulation off
466 TBENTRY 0FH, <DF_NULL> ; Define mickeys/pixel
467 TBENTRY 10H, <DF_NULL> ; Define update region
468 TBENTRY 11H, <DF_NULL> ; GENIUS: # of buttons
469 TBENTRY 12H, <DF_MOU_LGCURSOR> ; Graphics cursor block
470 TBENTRY 13H, <DF_NULL> ; Double-speed threshold
471 TBENTRY 14H, <DF_INVALID> ; Exchange IRQ routines
472 TBENTRY 15H, <DF_NULL> ; Get state buffer size
473 TBENTRY 16H, <DF_INVALID> ; Save state
474 TBENTRY 17H, <DF_INVALID> ; Restore state
475 TBENTRY 18H, <DF_INVALID> ; Set event handler
476 TBENTRY 19H, <DF_INVALID> ; Return event handler
477 TBENTRY 1AH, <DF_NULL> ; Set sensitivity
478 TBENTRY 1BH, <DF_NULL> ; Return sensitivity
479 TBENTRY 1CH, <DF_NULL> ; Set interrupt rate
480 TBENTRY 1DH, <DF_NULL> ; Define display page
481 TBENTRY 1EH, <DF_NULL> ; Return display page
482 TBENTRY 1FH, <DF_NULL> ; Disable mouse driver
483 TBENTRY 20H, <DF_NULL> ; Enable mouse driver
484 TBENTRY 21H, <DF_NULL> ; Software reset
485 TBENTRY 22H, <DF_NULL> ; Set language
486 TBENTRY 23H, <DF_NULL> ; Get language
487 TBENTRY 24H, <DF_NULL> ; Get misc. info
488 TBENTRY 25H, <DF_NULL> ; Get general driver info
489 TBENTRY 26H, <DF_NULL> ; Get maximum coordinates
490 TBENTRY 27H, <DF_NULL> ; Get masks & counts
491 TBENTRY 28H, <DF_NULL> ; Set video mode
492 TBENTRY 29H, <DF_INVALID> ; Enumerate video modes
493 TBENTRY 2AH, <DF_NULL> ; Get cursor hot spot
494 TBENTRY 2BH, <DF_INVALID> ; Load acceleration prof.
495 TBENTRY 2CH, <DF_INVALID> ; Get acceleration prof.
496 TBENTRY 2DH, <DF_INVALID> ; Select acc. profile
497 TBENTRY 2EH, <DF_INVALID> ; Set acc. profile names
498 TBENTRY 2FH, <DF_NULL> ; Hardware reset
499 TBENTRY 30H, <DF_NULL> ; Ballpoint information
500 TBENTRY 31H, <DF_NULL> ; Max. virtual coordinates
501 TBENTRY 32H, <DF_NULL> ; Get active adv. funcs.
502 TBENTRY 33H, <DF_INVALID> ; Switch settings etc.
503 TBENTRY 34H, <DF_INVALID> ; Get initialization file
504 TBENTRY 35H, <DF_NULL> ; LCD large pointer
505 TBENTRY 4DH, <DF_INVALID> ; Get copyright string
506 TBENTRY 6DH, <DF_INVALID> ; Get version string
507 TBEND
508
509;
510; Buffer for DOS interface
511;
512BUF_SEG WORD ? ; Current buffer (BUF?_SEG)
513BUF_SEL WORD ? ; Current buffer (G_BUF?_SEL)
514
515BUF1_SEG WORD ? ; 1st buffer (64KB)
516BUF2_SEG WORD ? ; 2nd buffer (4KB, for swapper)
517
518COUNTRYDATA LABEL BYTE
519CD_DATE WORD ?
520CD_CURRENCY BYTE 5 DUP (?)
521CD_1000_SEP BYTE 2 DUP (?)
522CD_DECIMAL_SEP BYTE 2 DUP (?)
523CD_DATE_SEP BYTE 2 DUP (?)
524CD_TIME_SEP BYTE 2 DUP (?)
525CD_FLAGS BYTE ?
526CD_CURRENCY_N BYTE ?
527CD_TIME BYTE ?
528CD_CASEMAP DWORD ?
529CD_LIST_SEP BYTE 2 DUP (?)
530CD_RESERVED BYTE 10 DUP (?)
531
532;
533; This table contains 256 bits; if bit i is set, byte i is a DBCS
534; lead byte.
535;
536DBCS_LEAD_TAB WORD (256 / 8 / 2) DUP (?)
537
538$INTERRUPT BYTE "Unexpected interrupt", 0
539$NMI BYTE "Nonmaskable interrupt (NMI) at ", 0
540$BAD_MOU_FUNC BYTE "Illegal moucall function code: ", 0
541$BAD_DOS_FUNC BYTE "Illegal syscall function code: ", 0
542$BAD_VIO_FUNC BYTE "Illegal viocall function code: ", 0
543$DOS_PARAM BYTE "Invalid arguments for syscall ", 0
544$EMERGENCY BYTE "Emergency exit", 0
545
546
547 IF DEBUG_DOSDUMP
548$DOSDUMP BYTE "DOSDUMP.000"
549$DOSDUMP_C = THIS BYTE - 1
550 BYTE 0
551 ENDIF
552
553SV_DATA ENDS
554
555
556SV_CODE SEGMENT
557
558 .386P
559
560 ASSUME CS:SV_CODE, DS:NOTHING
561
562 TALIGN 2
563CONV_TAB WORD D_INVALID ; DF_INVALID
564 WORD D_NULL ; DF_NULL
565 WORD D_WRITE ; DF_WRITE
566 WORD D_PATH ; DF_PATH
567 WORD D_TEXT ; DF_TEXT
568 WORD D_READ ; DF_READ
569 WORD D_SEEK ; DF_SEEK
570 WORD D_TMP ; DF_TMP
571 WORD D_INPUT ; DF_INPUT
572 WORD D_MOVE ; DF_MOVE
573 WORD D_DUP2 ; DF_DUP2
574 WORD D_CLOSE ; DF_CLOSE
575 WORD D_INVALID ; DF_IOCTL (handled before jumping)
576 WORD D_GETCWD ; DF_GETCWD
577 WORD D_EXIT ; DF_EXIT
578 WORD D_FFIRST ; DF_FFIRST
579 WORD D_FNEXT ; DF_FNEXT
580 WORD D_VERSION ; DF_VERSION
581 WORD D_EXEC ; DF_EXEC
582 WORD D_RETCODE ; DF_RETCODE
583 WORD D_STR_BP ; DF_STR_BP
584 WORD D_VESA ; DF_VESA
585 WORD D_VESAINFO ; DF_VESAINFO
586 WORD D_VESAMODE ; DF_VESAMODE
587 WORD D_MOU_GCURSOR ; DF_MOU_GCURSOR
588 WORD D_MOU_LGCURSOR ; DF_MOU_LGCURSOR
589 WORD D_COUNTRY ; DF_COUNTRY
590 WORD D_LOCK ; DF_LOCK
591 WORD D_TRUENAME ; DF_TRUENAME
592 WORD D_PATH_SI ; DF_PATH_SI
593 WORD D_DUP ; DF_DUP
594 WORD D_VIO11 ; DF_VIO11
595 WORD D_VIO12 ; DF_VIO12
596
597 .ERRE ($-CONV_TAB)/2 EQ DF_LAST+1
598
599
600;
601; All undefined interrupts go here
602;
603; This cannot happen, as undefined interrupts cannot be called
604; from the user program (CPL=3 & DPL=0) and all hardware interrupts
605; have their own vector. Yes, the supervisor could issue an
606; undefined software interrupt, but it doesn't. At least I hope so.
607;
608
609 ASSUME DS:NOTHING
610INTERRUPT: MOV AX, G_SV_DATA_SEL
611 MOV DS, AX
612 ASSUME DS:SV_DATA
613 LEA EDX, $INTERRUPT
614 CALL INT_MSG
615 JMP SHORT $
616
617 ASSUME DS:NOTHING
618NMI: MOV AX, G_SV_DATA_SEL
619 MOV DS, AX
620 ASSUME DS:SV_DATA
621 LEA EDX, $NMI
622 CALL INT_MSG
623 MOV AX, SS:[ESP+4] ; CS
624 CALL VWORD
625 MOV AL, ":"
626 CALL VCHAR
627 MOV EAX, SS:[ESP+0] ; EIP
628 CALL VDWORD
629 IF FALSE
630 MOV AL, " "
631 CALL VCHAR
632 MOV EAX, SS:[ESP+8] ; EFLAGS
633 CALL VDWORD
634 ENDIF
635 JMP SHORT $
636
637;
638; Display fatal error message (unexpected interrupt / NMI)
639;
640 ASSUME DS:SV_DATA
641INT_MSG PROC NEAR
642 MOV AX, G_VIDEO_SEL
643 MOV ES, AX
644 CALL VCLS
645 CALL VTEXT
646 RET
647INT_MSG ENDP
648
649
650;
651; Backward jump here (for processors with BIG prefetch queue)
652;
653RM_INT1: XOR EAX, EAX
654 MOV CR3, EAX ; Clear TLB
655 JMP FAR PTR RM_INT2 ; Reload CS, real mode!
656
657;
658; Call the real-mode interrupt INT_NO
659;
660 ASSUME DS:SV_DATA
661 TALIGN 4
662INT_RM0 PROC FAR
663 CLI
664 CMP PROFIL_COUNT, 0 ; Suspend generating RTC
665 JE SHORT NOPROF ; interrupts for the profiler
666 CALL PROFIL_SUSPEND
667 TALIGN 4
668NOPROF: MOV PMHWINT_ESP, ESP ; Save stack pointer
669 MOV PMHWINT_SS, SS ; and stack segment
670 MOV FRAME_PTR, BP ; After CLI!!!
671 MOV EAX, CR0
672 AND EAX, CR0_FPU ; Keep only FPU bits
673 MOV PM_CR0, EAX ; Save for switching back to PM
674 MOV EAX, CR0
675 AND EAX, NOT CR0_FPU ; Restore floating point
676 OR EAX, RM_CR0 ; bits of real/virtual mode
677 MOV CR0, EAX
678 XOR AX, AX
679 LLDT AX ; Zero LDTR
680 CMP VCPI_FLAG, FALSE ; Running under VCPI server?
681 JNE INT_VCPI ; Yes -> let the server do it
682 MOV AX, G_REAL_SEL ; Load values suitable for
683 MOV DS, AX ; real mode into all the
684 ASSUME DS:NOTHING ; segment registers
685 MOV ES, AX ; (see below for CS)
686 MOV FS, AX
687 MOV GS, AX
688 MOV SS, AX
689 MOV EAX, CR0
690 AND EAX, NOT (CR0_PG OR CR0_PE) ; Turn off paging and PM
691 MOV CR0, EAX
692 JMP SHORT RM_INT1 ; Flush prefetch queue
693;
694; ... real mode ...
695;
696 ASSUME DS:NOTHING
697 TALIGN 4
698RM_INT9:: MOV AX, G_SV_DATA_SEL
699 MOV DS, AX ; Make data accessible
700 ASSUME DS:SV_DATA
701 LSS ESP, PMHWINT_LSS ; Restore stack
702 AND TSS_BUSY, NOT 2 ; Otherwise exception on LTR
703 MOV AX, G_TSS_SEL
704 LTR AX ; Setup task
705 CMP PAGING, FALSE ; Use paging?
706 JE SHORT RM_INT10 ; No -> skip
707 MOV EAX, PAGE_DIR_PHYS
708 MOV CR3, EAX ; Setup page directory
709 MOV EAX, CR0
710 OR EAX, CR0_PG ; Enable paging
711 MOV CR0, EAX
712;
713; Common code for `manual' return from real mode and for VCPI
714;
715RM_INT10: MOV EAX, CR0
716 AND EAX, NOT CR0_FPU ; Restore floating point
717 OR EAX, PM_CR0 ; bits of protected mode
718 MOV CR0, EAX
719 RET ; FAR return!!!
720
721;
722; When running under a VCPI server, we return here from virtual mode
723;
724
725 ASSUME DS:NOTHING
726 TALIGN 4
727V2P_CONT:: MOV AX, G_SV_DATA_SEL
728 MOV DS, AX ; Make data accessible
729 ASSUME DS:SV_DATA
730 MOV ES, AX
731 MOV FS, AX
732 MOV GS, AX
733 LSS ESP, PMHWINT_LSS ; Setup stack
734 JMP SHORT RM_INT10 ; Floating point bits of CR0
735
736INT_RM0 ENDP
737
738
739 ASSUME DS:SV_DATA
740 TALIGN 4
741INT_RM PROC NEAR
742 PUSH EBP ; Save EBP
743 PUSHFD ; Save flags
744 SLDT AX
745 PUSH AX ; Save LDTR
746 CALLF16 G_SV_CODE_SEL, INT_RM0 ; FAR call!
747 MOV AX, G_SV_DATA_SEL ; Initialize all segment
748 MOV DS, AX ; registers
749 MOV ES, AX
750 MOV FS, AX
751 MOV GS, AX
752;
753; Important: Restore LDTR of interrupted program. Real/virtual mode may have
754; changed LDTR (INT 15H: extended memory). Actually, we zero LDTR after
755; entering real mode. We need the LDTR for popping the segment registers
756; of the interrupted program, which may reference the LDT.
757;
758 POP AX
759 LLDT AX ; Restore LDTR
760 CMP PROFIL_COUNT, 0
761 JE SHORT NOPROF
762 CLI ; Resume generating RTC
763 CALL PROFIL_RESUME ; interrupts for the profiler
764 TALIGN 4
765NOPROF: POPFD ; Restore flags
766 POP EBP ; Restore EBP
767 RET ; Done
768INT_RM ENDP
769
770;
771; This is the first interrupt vector used for redirecting IRQ0..IRQ7
772; and IRQ8..IRQ15, respectively. These variables are located in SV_CODE
773; as they are accessed with unknown segment registers (only CS is known
774; to be SV_CODE_SEL).
775;
776IRQ0_ADD BYTE ? ; Initialized by INIT_INT
777IRQ8_ADD BYTE ? ; Initialized by INIT_INT
778
779
780;
781; Entry points for hardware interrupts IRQ 0 to IRQ 7.
782;
783
784 ASSUME DS:NOTHING
785
786 IRP X, <0,1,2,3,4,5,6,7>
787 TALIGN 4
788PMINT&X: PUSH EAX ; Mock error code
789 PUSHAD ; Save all general registers
790 MOV CX, &X * 0100H + &X ; Compute real-mode interrupt
791 ADD CL, IRQ0_ADD ; number (in SV_CODE segment!)
792 JMP PMINT ; Common code
793 ENDM
794
795;
796; Entry points for hardware interrupts IRQ 8 to IRQ 15.
797;
798
799 ASSUME DS:NOTHING
800
801 IRP X, <8,9,10,11,12,13,14,15>
802 TALIGN 4
803PMINT&X: PUSH EAX ; Mock error code
804 PUSHAD ; Save all general registers
805 MOV CX, &X * 0100H + &X-8 ; Compute real-mode interrupt
806 ADD CL, IRQ8_ADD ; number (in SV_CODE segment!)
807 JMP PMINT ; Common code
808 ENDM
809
810;
811; Entry point for software interrupt 10H (video interface).
812;
813 TALIGN 4
814PMINT_10H: PUSH EAX ; Mock error code
815 PUSHAD ; Save all general registers
816 MOV CX, 1010H ; Real-mode interrupt number
817 JMP SHORT PMINT ; Common code
818
819;
820; Entry point for software interrupt 11H (equipment).
821;
822 TALIGN 4
823PMINT_11H: PUSH EAX ; Mock error code
824 PUSHAD ; Save all general registers
825 MOV CX, 1111H ; Real-mode interrupt number
826 JMP SHORT PMINT ; Common code
827
828;
829; Entry point for software interrupt 14H (RS-232 interface).
830;
831 TALIGN 4
832PMINT_14H: PUSH EAX ; Mock error code
833 PUSHAD ; Save all general registers
834 MOV CX, 1414H ; Real-mode interrupt number
835 JMP SHORT PMINT ; Common code
836
837;
838; Entry point for software interrupt 16H (keyboard interface).
839;
840 TALIGN 4
841PMINT_16H: PUSH EAX ; Mock error code
842 PUSHAD ; Save all general registers
843 MOV CX, 1616H ; Real-mode interrupt number
844 JMP SHORT PMINT ; Common code
845
846;
847; Entry point for software interrupt 17H (printer interface).
848;
849 TALIGN 4
850PMINT_17H: PUSH EAX ; Mock error code
851 PUSHAD ; Save all general registers
852 MOV CX, 1717H ; Real-mode interrupt number
853 JMP SHORT PMINT ; Common code
854
855;
856; Entry point for software interrupt 21H (DOS interface).
857;
858 TALIGN 4
859PMINT_21H: PUSH EAX ; Mock error code
860 PUSHAD ; Save all general registers
861 MOV CX, 2121H ; Real-mode interrupt number
862 JMP SHORT PMINT ; Common code
863
864;
865; Entry point for software interrupt 31H (DOS extender interface).
866;
867 TALIGN 4
868PMINT_31H: PUSH EAX ; Mock error code
869 PUSHAD ; Save all general registers
870 MOV CX, 3131H ; Real-mode interrupt number
871 JMP SHORT PMINT ; Common code
872
873;
874; Entry point for software interrupt 33H (mouse interface).
875;
876 TALIGN 4
877PMINT_33H: PUSH EAX ; Mock error code
878 PUSHAD ; Save all general registers
879 MOV CX, 3333H ; Real-mode interrupt number
880 JMP SHORT PMINT ; Common code
881
882;
883; Common code for protected-mode interrupts (hardware and software interrupts).
884;
885; Note: this code runs with interrupts masked.
886;
887 TALIGN 4
888PMINT: PUSH DS ; Save segment registers
889 PUSH ES
890 PUSH FS
891 PUSH GS
892 IF SER_FLAG
893 SERIAL "I"
894 ENDIF
895 CLD
896 MOV AX, G_SV_DATA_SEL
897 MOV DS, AX ; Make data segment available
898 ASSUME DS:SV_DATA
899 MOV EBP, ESP ; Setup stack frame pointer
900 SUB ESP, FRAME_SIZE ; Local variables
901PMINT_STACK_SNAP_SHOT: ; For documentation only
902 MOV INT_NO, CL ; Save interrupt number
903 MOV HW_INT_VEC, CH
904 CMP CH, 8 ; RTC interrupt?
905 JE RTC_INT ; Yes -> profile or reflect
906 IF FLOATING_POINT
907 CMP CH, 13 ; Coprocessor interrupt?
908 JE COPROC ; Yes -> map to SIGFPE
909SKIP_COPROC:
910 ENDIF
911 CMP CL, 21H ; DOS call interrupt?
912 JE DOSCALL ; Yes ->
913 CMP CL, 10H ; Video API interrupt?
914 JE VIOCALL ; Yes ->
915 CMP CL, 11H ; Equiment interrupt?
916 JE GENERIC_CALL ; Yes ->
917 CMP CL, 14H ; RS-232 API interrupt?
918 JE GENERIC_CALL ; Yes ->
919 CMP CL, 16H ; Keyboard API interrupt?
920 JE GENERIC_CALL ; Yes ->
921 CMP CL, 17H ; Printer API interrupt?
922 JE GENERIC_CALL ; Yes ->
923 CMP CL, 31H ; DOS extender API interrupt?
924 JE EXT_CALL ; Yes ->
925 CMP CL, 33H ; Mouse API interrupt?
926 JE MOUCALL ; Yes ->
927;
928; This is the simple case: just reissue the interrupt in real mode.
929;
930REFLECT: CALL INT_RM
931;
932; The STI in the following line has been removed in emx 0.8b to fix a stack
933; overflow problem with high speed communications and an interrupt controller
934; reprogrammed to AEOI mode.
935;
936;*** STI ; At the risk of stack overflow
937;
938; Back in protected mode, return to interrupted code (and check for signals)
939;
940PMINT_RET: CMP EMERGENCY_FLAG, FALSE ; Emergency exit pending?
941 JE SHORT SKIP_EMGCY
942 CALL EMERGENCY_EXIT
943SKIP_EMGCY: ADD ESP, FRAME_SIZE ; Remove local variables
944 CALL SIG_DELIVER_PENDING
945 IF SER_FLAG
946 SERIAL "i"
947 ENDIF
948 POP GS ; Restore segment registers
949 POP FS
950 POP ES
951 POP DS
952 POPAD ; Restore general registers
953 NOP ; Avoid 386 bug
954 ADD ESP, 4 ; Remove error code
955 IRETD ; End of interrupt routine
956 ; 32-bit interrupt gate!!!
957
958
959;
960; Syscall functions
961;
962 TALIGN 4
963SYSCALL_1: CALL DO_SYSCALL
964 JMP PMINT_RET
965
966;
967; Emergency exit
968;
969EMERGENCY_EXIT PROC NEAR
970 MOV EMERGENCY_FLAG, FALSE
971 LEA EDX, $EMERGENCY
972 CALL OTEXT
973 CALL OCRLF
974 MOV AX, 4CFFH
975 INT 21H
976EMERGENCY_EXIT ENDP
977
978;
979; Real-time clock interrupt (IRQ8).
980;
981 TALIGN 4
982RTC_INT: CMP PROFIL_COUNT, 0
983 JE REFLECT
984 CALL PROFIL_TICK
985 JMP PMINT_RET
986
987;
988; Coprocessor interrupt (IRQ13). Reset the BUSY pin and raise SIGFPE.
989;
990 TALIGN 4
991COPROC: CMP MACHINE, MACH_PC ; PC architecture?
992 JNE SKIP_COPROC ; No -> give up
993;
994; Reset the interrupt condition
995;
996 MOV AL, 00H ; Send a byte of zeros
997 OUT 0F0H, AL ; to reset the BUSY pin
998 MOV AL, 20H ; Send EOI command to the
999 OUT 0A0H, AL ; slave interrupt controller,
1000 OUT 20H, AL ; master interrupt controller
1001 FNCLEX ; Clear exceptions
1002;
1003; Raise SIGFPE
1004;
1005 MOV AL, 16 ; Exception 16: Coproc error
1006 JMP EXCEPT_FAKE ; Fake an exception
1007
1008COPROC_DONE: JMP PMINT_RET
1009
1010;
1011; DOS extender interface.
1012;
1013 TALIGN 4
1014EXT_CALL: STI
1015 CALL EXTAPI
1016 JMP PMINT_RET
1017
1018;
1019; DOS interface.
1020;
1021 ASSUME DS:SV_DATA
1022 ASSUME BP:PTR ISTACKFRAME
1023 TALIGN 4
1024DOSCALL: STI ; Be venturous!
1025 AND I_EFLAGS, NOT FLAG_C ; Clear carry flag (no error)
1026 MOV EAX, I_EAX ; Get EAX (we need only AX)
1027 CMP AH, 7FH ; Syscall functions?
1028 JE SHORT SYSCALL_1 ; Yes ->
1029 CALL REGS_TO_RM ; Set real-mode registers
1030;
1031; Apply umask for __creat()
1032;
1033 CMP BYTE PTR RM_AX[1], 3CH ; Create handle?
1034 JNE SHORT SKIP_CREAT ; No -> skip
1035 MOV BX, PROCESS_PTR ; Current process
1036 CMP BX, NO_PROCESS ; In user code?
1037 JE SHORT SKIP_CREAT ; No -> keep mode
1038 TEST (PROCESS PTR [BX]).P_UMASK, S_IWRITE
1039 JZ SHORT SKIP_CREAT ; Write perm. -> keep mode
1040 OR RM_CX, 1 ; Set read-only attribute
1041 TALIGN 4
1042;
1043; Get conversion flag for INT 21H functions, convert handles if appropriate.
1044;
1045SKIP_CREAT: MOV INP_HANDLE, NO_FILE_HANDLE ; Handle not converted
1046 MOV BL, BYTE PTR RM_AX[1] ; AH
1047 TBGET DOS_FUNCS ; Get conversion flag
1048 CMP AL, DF_IOCTL ; Use second table?
1049 JNE SHORT DOSCALL_1
1050 MOV BL, BYTE PTR RM_AX[0] ; AL
1051 TBGET IOCTL_FUNCS ; Get conversion flag
1052DOSCALL_1: MOV CONV_FLAG, AX ; Save conversion flag
1053 CMP PROCESS_PTR, NO_PROCESS ; Translate handles?
1054 JE SHORT DOSCALL_9 ; No -> skip
1055 TEST CONV_FLAG, DFH_IN ; Convert handle (input)?
1056 JZ SHORT DOSCALL_2 ; No -> check for output
1057 MOV AX, RM_BX ; Get process' handle
1058 MOV INP_HANDLE, AX ; Save this value
1059 CALL GET_HANDLE ; Convert to DOS handle
1060 MOV RM_BX, AX ; and store to BX
1061DOSCALL_2: TEST CONV_FLAG, DFH_OUT ; Convert handle (output)?
1062 JZ SHORT DOSCALL_3 ; No -> skip
1063 MOV AX, NO_FILE_HANDLE
1064 CALL NEW_HANDLE ; Slot available?
1065 JNC SHORT DOSCALL_3 ; Yes -> continue
1066 MOV I_EAX, EMFILE ; Too many open files
1067 OR BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
1068 JMP PMINT_RET ; Return to caller
1069;
1070; Check whether identical mapping should be used for handles 0 and 1.
1071; This can be done after calling GET_HANDLE because all functions
1072; for which DFM_STDIN or DFM_STDOUT is set, don't use an explicit
1073; file handle (that's why DFM_STDIN and DFM_STDOUT are required in
1074; the first place).
1075;
1076DOSCALL_3: TEST CONV_FLAG, DFM_STDIN ; Remap handle 0?
1077 JZ SHORT DOSCALL_4
1078 MOV AX, 0
1079 CALL MAP_HANDLE
1080 JC SHORT MAP_ERROR
1081DOSCALL_4: TEST CONV_FLAG, DFM_STDOUT ; Remap handle 1?
1082 JZ SHORT DOSCALL_9
1083 MOV AX, 1
1084 CALL MAP_HANDLE
1085 JNC SHORT DOSCALL_9
1086MAP_ERROR: MOV WORD PTR I_EAX+0, AX
1087 MOV WORD PTR I_EAX+2, 0
1088 OR BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
1089 JMP PMINT_RET
1090
1091;
1092; Dispatcher for INT 21H
1093;
1094 TALIGN 4
1095DOSCALL_9: MOVZX BX, BYTE PTR CONV_FLAG ; Get conversion flag
1096 SHL BX, 1
1097 JMP CONV_TAB[BX]
1098
1099;
1100; Dispatcher for other interrupts (use AX as conversion flag)
1101;
1102 TALIGN 4
1103INTCALL: MOV CONV_FLAG, AX ; No conversion at DOSCALL_RET
1104 MOV BX, AX
1105 SHL BX, 1
1106 JMP CONV_TAB[BX]
1107
1108;
1109; INT 10H -- video BIOS
1110;
1111VIOCALL: MOV INP_HANDLE, NO_FILE_HANDLE
1112 CALL REGS_TO_RM
1113 MOV BL, BYTE PTR RM_AX[1] ; AH
1114 TBGET VIO_FUNCS ; Get conversion flag
1115 JMP SHORT INTCALL
1116
1117D_VESA: MOV BL, BYTE PTR RM_AX[0] ; AL
1118 TBGET VESA_FUNCS ; Get conversion flag
1119 JMP SHORT INTCALL
1120
1121D_VIO11: MOV BL, BYTE PTR RM_AX[0] ; AL
1122 TBGET VIO11_FUNCS ; Get conversion flag
1123 JMP SHORT INTCALL
1124
1125D_VIO12: MOV BL, BYTE PTR RM_BX[0] ; BL
1126 TBGET VIO12_FUNCS ; Get conversion flag
1127 JMP SHORT INTCALL
1128
1129;
1130; INT 33H -- mouse driver
1131;
1132MOUCALL: MOV INP_HANDLE, NO_FILE_HANDLE
1133 CALL REGS_TO_RM
1134 MOV BX, RM_AX ; Get AX
1135 CMP BH, 0 ; AH=0?
1136 JNE D_INVALID ; No -> error
1137 TBGET MOU_FUNCS ; Get conversion flag
1138 JMP INTCALL
1139
1140;
1141; Generic software interrupt, no conversion
1142;
1143GENERIC_CALL: MOV INP_HANDLE, NO_FILE_HANDLE
1144 CALL REGS_TO_RM
1145 MOV AX, DF_NULL ; No conversion
1146 JMP INTCALL
1147
1148;
1149; Duplicate file handle
1150;
1151D_DUP: MOV BX, PROCESS_PTR
1152 CMP BX, NO_PROCESS ; Called from user process?
1153 JE D_NULL ; No -> directly call DOS
1154 MOV AX, RM_BX ; Handle
1155 CALL DO_DUP
1156D_DUP_COMMON: MOV WORD PTR I_EAX + 0, AX
1157 MOV WORD PTR I_EAX + 2, 0
1158 JNC SHORT D_DUP_FIN
1159 OR BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
1160D_DUP_FIN: JMP PMINT_RET ; DFE not set for D_DUP!
1161
1162;
1163; Force duplicate file handle
1164;
1165D_DUP2: MOV BX, PROCESS_PTR
1166 CMP BX, NO_PROCESS ; Called from user process?
1167 JE D_NULL ; No -> directly call DOS
1168 MOV AX, RM_BX ; Handle1
1169 MOV CX, RM_CX ; Handle2
1170 CALL DO_DUP2
1171 JMP D_DUP_COMMON
1172
1173;
1174; Invalid function
1175;
1176D_INVALID: MOV BL, BYTE PTR RM_AX[0]
1177 LEA EDX, $BAD_MOU_FUNC ; MOU function not supported
1178 CMP INT_NO, 33H
1179 JE SHORT DOSF_ERROR
1180 MOV BL, BYTE PTR RM_AX[1]
1181 LEA EDX, $BAD_VIO_FUNC ; VIO function not supported
1182 CMP INT_NO, 10H
1183 JE SHORT DOSF_ERROR
1184 LEA EDX, $BAD_DOS_FUNC ; DOS function not supported
1185DOSF_ERROR: PUSH BX ; Save function number (BL)
1186 CALL OTEXT ; Display message
1187 POP AX ; Restore function number (AL)
1188 CALL OBYTE ; Display hex byte
1189 MOV AX, 4CFFH ; Terminate program (255)
1190 INT 21H ; This is recursive!
1191
1192;
1193; Invalid arguments
1194;
1195DOSF_PARAM: LEA EDX, $DOS_PARAM ; Invalid arguments
1196 JMP DOSF_ERROR ; Abort
1197
1198;
1199; Convert output:
1200;
1201; Insert emx version
1202;
1203D_VERSION: CALL INT_RM ; Call DOS
1204 CALL REGS_FROM_RM ; Copy all general registers
1205 MOV WORD PTR I_EAX+2, 6D65H ; Indicate emx: "em"
1206 JMP DOSCALL_RET ; Done
1207
1208
1209;
1210; Convert input:
1211;
1212; DS:EDX points to "$" terminated string
1213;
1214 TALIGN 4
1215D_TEXT: MOV AL, "$" ; Look for "$"
1216 MOV AH, FALSE ; Not a path name
1217 XOR EBX, EBX ; Don't add
1218 CALL G_DELIM
1219 JMP DOSCALL_RET ; Done
1220
1221
1222;
1223; Convert input and output:
1224;
1225; DS:EDX points to 0 terminated string (path)
1226; DS:ESI points to DTA (43 bytes)
1227;
1228 TALIGN 4
1229D_FFIRST: CALL SET_DTA_1 ; Uses OFFSET_1
1230 MOV ESI, I_EDX
1231 MOV AL, 00H ; Terminator
1232 MOV AH, NOT FALSE ; It's a path name
1233 XOR EBX, EBX
1234 MOV EDI, OFFSET_2
1235 MOV RM_DX, DI ; Offset of buffer
1236 CALL I_DELIM
1237D_FFIRST_1: PUSH I_EDX ; Save EDX (argument)
1238 CALL INT_RM ; Call DOS
1239 CALL REGS_FROM_RM ; Retrieve real-mode registers
1240 POP I_EDX ; Restore EDX (of caller)
1241 MOV AX, I_DS ; AX:EDI = destination
1242 MOV EDI, I_ESI
1243 MOV ECX, 43
1244 CALL MOVE_FROM_RM ; Copy from real-mode buffer
1245 JMP DOSCALL_RET
1246
1247;
1248; Convert input and output:
1249;
1250; DS:ESI points to DTA (43 bytes)
1251;
1252 TALIGN 4
1253D_FNEXT: CALL SET_DTA_1 ; Uses OFFSET_1
1254 MOV AX, I_DS
1255 MOV ESI, I_ESI
1256 MOV EDI, OFFSET_1
1257 MOV ECX, 43
1258 CALL MOVE_TO_RM
1259 JMP SHORT D_FFIRST_1
1260
1261;
1262;
1263; Convert input:
1264;
1265; DS:EDX points to 0 terminated string (path) -> DS:DX
1266; DS:EDI points to 0 terminated string (path) -> ES:DI
1267;
1268 TALIGN 4
1269D_MOVE: MOV ESI, I_EDI
1270 MOV AL, 00H ; Terminator
1271 MOV AH, NOT FALSE ; It's a path name
1272 XOR EBX, EBX
1273 MOV EDI, OFFSET_2
1274 MOV RM_DI, DI ; Offset of buffer
1275 CALL I_DELIM
1276 ; fall through to D_PATH
1277;
1278; Convert input:
1279;
1280; DS:EDX points to 0 terminated string (path)
1281;
1282 TALIGN 4
1283D_PATH: MOV AL, 0 ; Look for zeros
1284 MOV AH, NOT FALSE ; It's a path name
1285 XOR EBX, EBX ; Don't add
1286 CALL G_DELIM
1287 JMP DOSCALL_RET
1288
1289;
1290; Convert input:
1291;
1292; DS:ESI points to 0 terminated string (path)
1293;
1294D_PATH_SI: MOV AL, 0 ; Look for zeros
1295 MOV AH, NOT FALSE ; It's a path name
1296 XOR EBX, EBX ; Don't add
1297 MOV ESI, I_ESI
1298 MOV EDI, OFFSET_1
1299 MOV RM_SI, DI ; Offset of buffer
1300 CALL I_DELIM
1301 PUSH I_ESI ; Save ESI (argument)
1302 CALL INT_RM ; Call DOS
1303 CALL REGS_FROM_RM ; Retrieve real-mode registers
1304 POP I_ESI ; Restore ESI (of caller)
1305 JMP DOSCALL_RET
1306
1307;
1308; Convert input/output:
1309;
1310; DS:EDX points to 0 terminated string (path) + 13 bytes
1311;
1312 TALIGN 4
1313D_TMP: MOV AL, 0 ; Look for zeros
1314 MOV AH, NOT FALSE ; It's a path name
1315 MOV EBX, 13 ; Add 13 bytes
1316 CALL G_DELIM
1317 MOV AX, I_DS ; AX:EDI = destination
1318 MOV EDI, I_EDX
1319 CALL MOVE_FROM_RM ; Copy from real-mode buffer
1320 JMP DOSCALL_RET
1321
1322;
1323; Convert input/output:
1324;
1325; DS:EDX points to buffer, length: first byte + 2
1326;
1327 TALIGN 4
1328D_INPUT: MOV AX, I_DS
1329 MOV ESI, I_EDX
1330 MOV ES, AX
1331 MOVZX ECX, BYTE PTR ES:[ESI]
1332 ADD ECX, 2
1333 PUSH ECX
1334 MOV EDI, OFFSET_1
1335 MOV RM_DX, DI ; Offset of buffer
1336 CALL MOVE_TO_RM
1337 CALL INT_RM
1338 POP ECX
1339 MOV AX, I_DS
1340 MOV EDI, I_EDX
1341 CALL MOVE_FROM_RM
1342 JMP DOSCALL_RET
1343
1344;
1345; Convert output:
1346;
1347; DS:ESI points to zero terminated string
1348;
1349 TALIGN 4
1350D_GETCWD: MOV RM_SI, OFFSET_1 ; Offset of buffer
1351 CALL INT_RM
1352 TEST RM_FLAGS, FLAG_C
1353 JNZ DOSCALL_RET
1354 MOV EDI, I_ESI
1355 MOV AX, I_DS
1356 CALL MOVEZ_FROM_RM
1357 JMP DOSCALL_RET
1358
1359;
1360; Input (registers of caller):
1361; BX = handle
1362; DS:EDX = buffer
1363; ECX = number of bytes
1364;
1365; Output (registers of caller):
1366; EAX = number of bytes or error code
1367; CY=1 : error
1368;
1369; Truncate the file at the current position of the file pointer (in contrast
1370; to the statement in system.doc). This is required for the implementation
1371; of _ftruncate().
1372;
1373 TALIGN 4
1374D_WRITE: MOV AX, WORD PTR I_EAX
1375 MOV N_AX, AX
1376 MOV EAX, I_ECX
1377 MOV NREQ, EAX
1378 PUSH EAX ; Save caller's ECX
1379 MOV EAX, I_EDX
1380 MOV NPTR, EAX
1381 PUSH EAX ; Save caller's EDX
1382 MOV I_EAX, 0 ; Result := 0 (EAX)
1383D_WRITE1: MOV EAX, NREQ
1384 CMP EAX, 0FFFFH - OFFSET_1
1385 JBE SHORT D_WRITE2
1386 MOV AX, 0FE00H ; 64K - 512
1387D_WRITE2: MOV RM_CX, AX
1388 MOV RM_DX, OFFSET_1 ; Offset of buffer
1389 MOV AX, I_DS ; AX:ESI = source
1390 MOV ESI, NPTR
1391 MOVZX ECX, RM_CX ; Size of buffer
1392 MOV EDI, OFFSET_1
1393 MOV RM_DX, DI ; Offset of buffer
1394 CALL MOVE_TO_RM ; Copy to real-mode buffer
1395 MOV AX, N_AX
1396 MOV RM_AX, AX
1397 CALL INT_RM ; Call DOS
1398 TEST RM_FLAGS, FLAG_C ; Error?
1399 JNZ SHORT D_WRITE_ERR
1400 MOV AX, RM_AX ; Number of bytes written
1401 TEST AX, AX ; Zero?
1402 JZ SHORT D_WRITE_END ; Yes -> done
1403 MOVZX ECX, AX
1404 ADD I_EAX, ECX ; Update return value
1405 CMP AX, RM_CX ; Less than requested?
1406 JB SHORT D_WRITE_END ; Yes -> done
1407 ADD NPTR, ECX
1408 SUB NREQ, ECX
1409 JNZ SHORT D_WRITE1
1410 JMP SHORT D_WRITE_END
1411
1412D_WRITE_ERR: MOVZX EAX, RM_AX ; Copy error code
1413 MOV I_EAX, EAX
1414D_WRITE_END: MOV AL, RM_FLAGS ; Copy flags
1415 MOV BYTE PTR I_EFLAGS[0], AL
1416 POP I_EDX ; Restore caller's EDX
1417 POP I_ECX ; Restore caller's ECX
1418 JMP DOSCALL_RET ; Done
1419
1420;
1421; Input (registers of caller):
1422; BX = handle
1423; DS:EDX = buffer
1424; ECX = number of bytes
1425;
1426; Output (registers of caller):
1427; EAX = number of bytes or error code
1428; CY=1 : error
1429;
1430 TALIGN 4
1431D_READ: CMP BYTE PTR RM_AX[1], 3FH ; AH=3FH (read handle)?
1432 JNE SHORT D_READ_10
1433 CMP RM_BX, 0 ; Handle = stdin?
1434 JNE SHORT D_READ_10
1435 TEST STDIN_TERMIO.C_LFLAG, IDEFAULT
1436 JNZ SHORT D_READ_10
1437 CMP PROCESS_PTR, NO_PROCESS
1438 JE SHORT D_READ_10
1439 TEST I_CS, 3 ; Called from user code?
1440 JZ SHORT D_READ_10 ; No ->
1441 PUSH RM_BX
1442 MOV RM_AX, 4400H ; IOCTL: Get device data
1443 CALL INT_RM
1444 TEST RM_FLAGS, FLAG_C ; Error?
1445 JNZ SHORT D_READ_09 ; Yes -> continue
1446 TEST RM_DX, 80H ; Device?
1447 JZ SHORT D_READ_09 ; No -> continue
1448 TEST RM_DX, 01H ; Console input device?
1449 JZ SHORT D_READ_09 ; No -> continue
1450 POP RM_BX ; Cleanup stack
1451 MOV ES, I_DS
1452 MOV EDI, I_EDX
1453 MOV ECX, I_ECX
1454 CALL TERMIO_READ
1455 MOV I_EAX, EAX
1456 JNC D_READ_01
1457 OR I_EFLAGS, FLAG_C
1458D_READ_01: MOV AX, INP_HANDLE
1459 CMP AX, NO_FILE_HANDLE ; Input handle converted?
1460 JE SHORT D_READ_02 ; No -> skip
1461 MOV WORD PTR I_EBX, AX ; Store to (E)BX
1462D_READ_02: JMP PMINT_RET
1463
1464D_READ_09: CALL REGS_TO_RM
1465 POP RM_BX
1466D_READ_10: MOV AX, WORD PTR I_EAX
1467 MOV N_AX, AX
1468 MOV EAX, I_ECX
1469 MOV NREQ, EAX
1470 PUSH EAX ; Save caller's ECX
1471 MOV EAX, I_EDX
1472 MOV NPTR, EAX
1473 PUSH EAX ; Save caller's EDX
1474 MOV I_EAX, 0 ; 0 bytes read
1475D_READ1: MOV EAX, NREQ
1476 CMP EAX, 0FFFFH - OFFSET_1
1477 JBE SHORT D_READ2
1478 MOV AX, 0FE00H ; 64K - 512
1479D_READ2: MOV RM_CX, AX
1480 MOV RM_DX, OFFSET_1 ; Offset of buffer
1481 MOV AX, N_AX
1482 MOV RM_AX, AX
1483 CALL INT_RM ; Call DOS
1484 TEST RM_FLAGS, FLAG_C ; Error?
1485 JNZ SHORT D_READ_ERR
1486 MOVZX ECX, RM_AX ; Get number of bytes read
1487 JECXZ D_READ3 ; EOF -> done
1488 MOV AX, I_DS ; AX:EDI = destination
1489 MOV EDI, NPTR
1490 CALL MOVE_FROM_RM ; Copy from real-mode buffer
1491 ADD I_EAX, ECX ; Adjust return value (EAX)
1492 CMP CX, RM_CX ; All bytes of this chunk read?
1493 JNE SHORT D_READ3 ; No -> done
1494 ADD NPTR, ECX ; Move pointer
1495 SUB NREQ, ECX ; Decrement byte count
1496 JNZ SHORT D_READ1 ; Not done -> repeat
1497D_READ3: JMP SHORT D_READ_END
1498
1499D_READ_ERR: MOVZX EAX, RM_AX ; Copy error code
1500 MOV I_EAX, EAX
1501D_READ_END: MOV AL, RM_FLAGS ; Copy flags
1502 MOV BYTE PTR I_EFLAGS[0], AL
1503 POP I_EDX ; Restore caller's EDX
1504 POP I_ECX ; Restore caller's ECX
1505 JMP DOSCALL_RET ; Done
1506
1507
1508;
1509; Convert input/output:
1510;
1511; EDX -> CX:DX
1512; Call DOS
1513; DX:AX -> EAX
1514;
1515 TALIGN 4
1516D_SEEK: MOV EAX, I_EDX ; Get EDX
1517 MOV RM_DX, AX ; Store lower word
1518 SHR EAX, 16 ; Get upper word
1519 MOV RM_CX, AX ; Store upper word
1520 CALL INT_RM ; Call DOS
1521 XOR EAX, EAX ; Clear upper word of EAX
1522 TEST RM_FLAGS, FLAG_C ; Error?
1523 JNZ SHORT D_SEEK_1 ; Yes -> no conversion
1524 MOV AX, RM_DX ; Get DX
1525 SHL EAX, 16 ; and put it into upper word
1526D_SEEK_1: MOV AX, RM_AX ; Put AX into lower word
1527 MOV I_EAX, EAX ; of EAX
1528 MOV AL, RM_FLAGS ; Copy flags
1529 MOV BYTE PTR I_EFLAGS[0], AL
1530 JMP DOSCALL_RET ; Done
1531
1532;
1533; Close a file handle
1534;
1535; Note: When called from user code no translation of error codes
1536; is done because DO_CLOSE already returns errno value.
1537; DO_CLOSE in turn may invoke this code via INT 21H. In that
1538; case (called from the kernel), error translation is performed,
1539; but the handle is not translated.
1540;
1541 TALIGN 4
1542D_CLOSE: MOV BX, PROCESS_PTR
1543 CMP BX, NO_PROCESS ; Called from user process?
1544 JE D_NULL ; No -> no translation
1545 MOV AX, RM_BX ; This is the handle
1546 CALL DO_CLOSE ; Close the handle
1547 JNC SHORT D_CLOSE_FIN ; No error -> done
1548D_CLOSE_ERROR: MOV WORD PTR I_EAX+0, AX ; Return errno in EAX
1549 MOV WORD PTR I_EAX+2, 0
1550 OR BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
1551D_CLOSE_FIN: JMP PMINT_RET ; Don't translate error code!
1552
1553;
1554; Exit
1555;
1556 TALIGN 4
1557D_EXIT: TEST I_CS, 3 ; Called from user program?
1558 JZ SHORT D_EXIT_QUIT ; No -> exit to DOS
1559 MOV SI, PROCESS_PTR ; Current process
1560 CMP SI, NO_PROCESS ; No current process?
1561 JE SHORT D_EXIT_QUIT ; Yes -> impossible (go DOS)
1562 ASSUME SI:PTR PROCESS
1563;
1564; ...to do: process 0 becomes parent process of all children
1565;
1566 MOV AL, BYTE PTR I_EAX ; Get return code
1567 MOV [SI].P_RC, AL ; Store it
1568 MOV EAX, [SI].P_PPID ; Get parent process ID
1569 TEST EAX, EAX ; Root process?
1570 JZ SHORT D_EXIT_QUIT ; Yes -> return to DOS
1571 CALL FIND_PROCESS ; Find parent process
1572 CMP BX, NO_PROCESS ; Does parent process exist?
1573 JZ SHORT D_EXIT_QUIT ; No -> cannot happen, quit
1574 ASSUME BX:PTR PROCESS
1575 MOV PROCESS_PTR, BX ; Switch to parent process
1576 MOV PROCESS_SIG, BX
1577 MOV EAX, I_EAX ; Get return code
1578 AND EAX, 0FFH ; Use only lower 8 bits
1579 TEST [BX].P_FLAGS, PF_PSEUDO_ASYNC ; Pseudo async?
1580 JNZ SHORT D_EXIT_PSEUDO ; Yes -> don't overwrite PID
1581 MOV [BX].P_SPAWN_RC, EAX ; Store the return code
1582 JMP SHORT D_EXIT_RESTORE ; Continue
1583D_EXIT_PSEUDO: MOV [BX].P_RC, AL ; Store the return code
1584D_EXIT_RESTORE: CALL REST_PROCESS ; Restore parent process
1585 MOV BX, SI ; The dying process
1586 PUSH [BX].P_NUMBER ; Save for FPUEMU_ENDPROC
1587 TEST [BX].P_FLAGS, PF_DEBUG ; In debugging mode?
1588 JZ SHORT D_EXIT_1 ; No -> kill process
1589 CALL ZOMBIE_PROCESS ; Make process defunct
1590 JMP SHORT D_EXIT_2
1591D_EXIT_1: CALL REMOVE_PROCESS ; Thoroughly kill process
1592D_EXIT_2: CALL BREAK_AFTER_IRET ; Allow debugging
1593 POP EAX ; P_NUMBER of the dead process
1594 CALL FPUEMU_ENDPROC ; Notify FPU emulator
1595 JMP DOSCALL_RET ; Continue with parent
1596 ASSUME BX:NOTHING
1597 ASSUME SI:NOTHING
1598;
1599; Exit to DOS
1600;
1601D_EXIT_QUIT: CMP FP_FLAG, FP_387 ; 387 available?
1602 JNE SHORT EQUIT1 ; No -> skip
1603 FNINIT ; Initialize
1604EQUIT1: CALL DEBUG_QUIT ; Swapper statistics
1605 XOR EAX, EAX
1606 MOV DR7, EAX ; Avoid unexpected behaviour
1607 JMP SHORT D_NULL
1608
1609;
1610; No conversion
1611;
1612 TALIGN 4
1613D_NULL: CALL INT_RM ; Call DOS
1614 CALL REGS_FROM_RM ; Copy all general registers
1615 JMP DOSCALL_RET ; Done
1616
1617;
1618; Just check for supervisor code
1619;
1620 TALIGN 4
1621D_RETCODE: TEST I_CS, 3 ; Called from supervisor?
1622 JNZ D_INVALID ; No -> bad function code
1623 JMP SHORT D_NULL ; No conversion
1624
1625;
1626; Load and execute (a DOS) program
1627;
1628 TALIGN 4
1629D_EXEC: TEST I_CS, 3 ; Called from supervisor?
1630 JNZ D_INVALID ; No -> bad function code
1631 MOV AX, SV_DATA ; Load real-mode segment
1632 MOV RM_DS, AX ; registers
1633 MOV RM_ES, AX
1634 CALL INT_RM
1635 MOV AX, RM_AX
1636 MOV WORD PTR I_EAX, AX
1637 MOV AL, RM_FLAGS
1638 MOV BYTE PTR I_EFLAGS[0], AL
1639 JMP DOSCALL_RET
1640
1641;
1642; Convert input:
1643;
1644; EBP points to null-terminated string (-> ES:BP)
1645;
1646 TALIGN 4
1647D_STR_BP: MOV AL, 0 ; Look for 0
1648 MOV AH, FALSE ; Not a path name
1649 XOR EBX, EBX ; Don't add
1650 MOV ESI, I_EBP
1651 MOV EDI, OFFSET_1
1652 MOV RM_BP, DI ; Offset of buffer
1653 CALL I_DELIM
1654 PUSH I_EBP ; Save EBP (of caller)
1655 CALL INT_RM ; Call interrupt
1656 CALL REGS_FROM_RM ; Retrieve real-mode registers
1657 POP I_EBP ; Restore EBP (of caller)
1658 JMP DOSCALL_RET ; Done
1659
1660
1661;
1662; Convert output of VESA function 0.
1663;
1664; EDI (-> ES:DI) points to a 256-byte buffer on entry which is filled-in
1665; by the function. There are two pointers to secondary buffers in the
1666; buffer. We have to copy the data pointed to by these pointers into
1667; the process' address space.
1668;
1669 TALIGN 4
1670D_VESAINFO: MOV RM_DI, OFFSET_1 ; Offset of buffer
1671 PUSH I_EDI ; Save EDI (of caller)
1672 CALL INT_RM ; Call interrupt
1673 CALL REGS_FROM_RM ; Retrieve real-mode registers
1674 POP I_EDI ; Restore EDI (of caller)
1675;
1676; Copy 256-byte buffer
1677;
1678 MOV AX, I_DS ; AX:EDI = destination
1679 MOV EDI, I_EDI
1680 MOV ECX, 256
1681 CALL MOVE_FROM_RM ; Copy from real-mode buffer
1682 CMP RM_AX, 004FH ; Successful?
1683 JNE DOSCALL_RET ; No -> don't convert pointers
1684;
1685; Allocate a page in the process address space for the secondary buffers
1686;
1687 MOV DI, PROCESS_PTR
1688 ASSUME DI:PTR PROCESS
1689 MOV EAX, [DI].P_VESAINFO_PTR
1690 TEST EAX, EAX
1691 JNZ SHORT DVI_REUSE
1692 MOV ECX, 1
1693 CALL ADD_PAGES
1694 TEST EAX, EAX
1695 JZ SHORT DVI_FAIL
1696 MOV [DI].P_VESAINFO_PTR, EAX
1697DVI_REUSE: MOV EDI, EAX
1698;
1699; Copy the OEM name
1700;
1701 MOV ES, I_DS
1702 MOV ESI, I_EDI
1703 XCHG EAX, ES:[ESI+06H] ; Pointer to OEM name
1704 CALL ACCESS_LOWMEM
1705 MOV AX, G_LOWMEM_SEL
1706 MOV FS, AX
1707 MOV ECX, 128 ; Maximum string length
1708DVI_OEM_1: MOV AL, FS:[EBX]
1709 TEST AL, AL
1710 JZ SHORT DVI_OEM_2
1711 INC EBX
1712 STOS BYTE PTR ES:[EDI]
1713 LOOP DVI_OEM_1
1714DVI_OEM_2: XOR AL, AL
1715 STOS BYTE PTR ES:[EDI]
1716;
1717; Copy the mode list
1718;
1719 INC EDI ; Make the address even
1720 AND EDI, NOT 1
1721 MOV EAX, EDI
1722 XCHG EAX, ES:[ESI+0EH] ; Pointer to video modes
1723 CALL ACCESS_LOWMEM
1724 MOV ECX, (4096 - 128) / 2 - 1
1725DVI_MODES_1: MOV AX, FS:[EBX]
1726 CMP AX, 0FFFFH
1727 JE SHORT DVI_MODES_2
1728 ADD EBX, 2
1729 STOS WORD PTR ES:[EDI]
1730 LOOP DVI_MODES_1
1731DVI_MODES_2: MOV AX, 0FFFFH
1732 STOS WORD PTR ES:[EDI]
1733 JMP DOSCALL_RET ; Done
1734
1735;
1736; Function call failed, invalidate the two pointers.
1737;
1738DVI_FAIL: MOV ES, I_DS
1739 MOV ESI, I_EDI
1740 MOV DWORD PTR ES:[ESI+06H], 0
1741 MOV DWORD PTR ES:[ESI+0EH], 0
1742 JMP DOSCALL_RET
1743
1744 ASSUME DI:NOTHING
1745
1746;
1747; Convert output of VESA function 1.
1748;
1749; EDI (-> ES:DI) points to a 256-byte buffer on entry which is filled-in
1750; by the function. There's one pointer in the buffer which points to
1751; a function. Set that pointer to NULL.
1752;
1753 TALIGN 4
1754D_VESAMODE: MOV RM_DI, OFFSET_1 ; Offset of buffer
1755 PUSH I_EDI ; Save EDI (of caller)
1756 CALL INT_RM ; Call interrupt
1757 CALL REGS_FROM_RM ; Retrieve real-mode registers
1758 POP I_EDI ; Restore EDI (of caller)
1759;
1760; Copy 256-byte buffer
1761;
1762 MOV AX, I_DS ; AX:EDI = destination
1763 MOV EDI, I_EDI
1764 MOV ECX, 256
1765 CALL MOVE_FROM_RM ; Copy from real-mode buffer
1766 MOV ES, I_DS
1767 MOV ESI, I_EDI
1768;
1769; Invalidate pointer to window positioning function (same as AX=4F05H)
1770;
1771 MOV DWORD PTR ES:[ESI+0CH], 0
1772 JMP DOSCALL_RET ; Done
1773
1774;
1775; Convert input
1776;
1777; EDX points 64-byte buffer (-> ES:DX)
1778;
1779 TALIGN 4
1780D_MOU_GCURSOR: MOV AX, I_DS
1781 MOV ESI, I_EDX
1782 PUSH ESI ; Save EDX (of caller)
1783 MOV ES, AX ; Source: AX:ESI
1784 MOV ECX, 64 ; Copy 2*16 16-bit words
1785 MOV EDI, OFFSET_1 ; to real-mode buffer
1786 MOV RM_DX, DI ; Offset of buffer
1787 CALL MOVE_TO_RM
1788 CALL INT_RM
1789 POP I_EDX ; Restore EDX (of caller)
1790 JMP DOSCALL_RET
1791
1792;
1793; Convert input
1794;
1795; EDX points to a buffer (-> ES:DX). The size of the buffer is
1796; BH * CH * 4 bytes.
1797;
1798 TALIGN 4
1799D_MOU_LGCURSOR: MOV AL, BYTE PTR RM_BX[1] ; BH
1800 MUL BYTE PTR RM_CX[1] ; CH
1801 MOVZX ECX, AX ; ECX = BH * CH
1802 SHL ECX, 2 ; Multiply by 4
1803 MOV AX, I_DS
1804 MOV ESI, I_EDX
1805 PUSH ESI ; Save EDX (of caller)
1806 MOV ES, AX ; Source: AX:ESI
1807 MOV EDI, OFFSET_1 ; to real-mode buffer
1808 MOV RM_DX, DI ; Offset of buffer
1809 CALL MOVE_TO_RM
1810 CALL INT_RM
1811 POP I_EDX ; Restore EDX (of caller)
1812 JMP DOSCALL_RET
1813
1814;
1815; Convert output:
1816;
1817; DS:EDX (input) points to buffer, length: 34 bytes
1818;
1819 TALIGN 4
1820D_COUNTRY: CMP RM_DX, 0FFFFH
1821 JE SHORT D_COUNTRY_SET
1822 MOV RM_DX, OFFSET_1
1823 CALL INT_RM
1824 MOV AX, I_DS
1825 MOV EDI, I_EDX
1826 MOV ECX, 34
1827 CALL MOVE_FROM_RM
1828D_COUNTRY_1: CALL REGS_FROM_RM
1829 JMP DOSCALL_RET
1830
1831D_COUNTRY_SET: CALL INT_RM
1832 JMP D_COUNTRY_1
1833
1834;
1835; Convert input:
1836;
1837; EDX -> CX:DX
1838; EDI -> SI:DI
1839;
1840 TALIGN 4
1841D_LOCK: MOV EAX, I_EDX
1842 PUSH EAX
1843 MOV RM_DX, AX
1844 SHR EAX, 16
1845 MOV RM_CX, AX
1846 MOV EAX, I_EDI
1847 PUSH EAX
1848 MOV RM_DI, AX
1849 SHR EAX, 16
1850 MOV RM_SI, AX
1851 CALL INT_RM
1852 CALL REGS_FROM_RM
1853 POP I_EDI
1854 POP I_EDX
1855 JMP DOSCALL_RET
1856
1857;
1858; Convert input: ASCIZ ESI -> DS:SI, EDI -> ES:DI
1859; Convert output: ASCIZ EDI
1860;
1861 TALIGN 4
1862D_TRUENAME: MOV AL, 0 ; Look for 0
1863 MOV AH, NOT FALSE ; It's a path name
1864 XOR EBX, EBX ; Don't add
1865 MOV ESI, I_ESI
1866 MOV EDI, OFFSET_2
1867 MOV RM_SI, DI ; Offset of buffer
1868 CALL I_DELIM
1869 MOV RM_DI, OFFSET_1
1870 PUSH I_ESI ; Save EDI and ESI (of caller)
1871 PUSH I_EDI
1872 CALL INT_RM
1873 CALL REGS_FROM_RM
1874 POP I_EDI
1875 POP I_ESI
1876 TEST I_EFLAGS, FLAG_C ; Error?
1877 JNZ SHORT D_TRUENAME_1 ; Yes -> skip
1878 MOV AX, I_ES
1879 MOV EDI, I_EDI
1880 CALL MOVEZ_FROM_RM ; Copies from OFFSET_1
1881D_TRUENAME_1: JMP DOSCALL_RET
1882
1883
1884;
1885; Return from DOS call
1886;
1887 TALIGN 4
1888DOSCALL_RET: MOV AX, INP_HANDLE
1889 CMP AX, NO_FILE_HANDLE ; Input handle converted?
1890 JE SHORT DOSCALL_RET1 ; No -> skip
1891 MOV WORD PTR I_EBX, AX ; Store to (E)BX
1892DOSCALL_RET1: TEST CONV_FLAG, DFH_OUT ; New handle?
1893 JZ SHORT DOSCALL_RET2
1894 CMP PROCESS_PTR, NO_PROCESS ; Called from user process?
1895 JE SHORT DOSCALL_RET2 ; No -> skip
1896 TEST I_EFLAGS, FLAG_C ; Error?
1897 JNZ SHORT DOSCALL_RET2 ; Yes -> skip
1898 MOV AX, WORD PTR I_EAX ; Get DOS handle
1899 CALL NEW_HANDLE ; New slot
1900 MOV I_EAX, EAX ; Return translated handle
1901DOSCALL_RET2: TEST CONV_FLAG, DFE ; Convert error code?
1902 JZ SHORT DOSCALL_RET3 ; No -> skip
1903 TEST I_EFLAGS, FLAG_C ; Error?
1904 JZ SHORT DOSCALL_RET3 ; No -> skip
1905 MOV AX, WORD PTR I_EAX ; Get error code
1906 CALL DOS_ERROR_TO_ERRNO ; Translate error code
1907 MOV I_EAX, EAX ; Put errno into EAX
1908DOSCALL_RET3: JMP PMINT_RET
1909
1910 ASSUME BP:NOTHING
1911
1912;
1913; In: EBX Number of bytes to move beyond terminator
1914; AL Terminator
1915; AH Path name flag
1916;
1917; Out: ECX Buffer size
1918;
1919 ASSUME DS:SV_DATA
1920 ASSUME BP:PTR ISTACKFRAME
1921G_DELIM PROC NEAR
1922 MOV ESI, I_EDX
1923 MOV EDI, OFFSET_1
1924 MOV RM_DX, DI ; Offset of buffer
1925 CALL I_DELIM
1926 PUSH ECX ; Save ECX (buffer size)
1927 PUSH I_EDX ; Save EDX (argument)
1928 CALL INT_RM ; Call DOS
1929 CALL REGS_FROM_RM ; Retrieve real-mode registers
1930 POP I_EDX ; Restore EDX (of caller)
1931 POP ECX ; Restore ECX (buffer size)
1932 RET
1933 ASSUME BP:NOTHING
1934G_DELIM ENDP
1935
1936
1937;
1938; In: ESI Pointer to argument
1939; EDI Offset in buffer
1940; EBX Number of bytes to move beyond terminator
1941; AL Terminator
1942; AH Path name flag (for truncation). Non-zero if path name
1943;
1944 ASSUME DS:SV_DATA
1945 ASSUME BP:PTR ISTACKFRAME
1946I_DELIM PROC NEAR
1947 PUSH AX ; Save terminator and flag
1948 PUSH EDI ; Save offset
1949 MOV ES, I_DS ; ES:EDI points to argument
1950 MOV ECX, 0FFFFH
1951 SUB ECX, EDI ; Maximum length
1952 MOV EDI, ESI
1953 CLD ; Incrementing
1954 REPNE SCAS BYTE PTR ES:[EDI] ; Look for terminator
1955 JECXZ IDELIM_2 ; Not found -> abort
1956 MOV ECX, EDI
1957 SUB ECX, ESI ; Length of string
1958 ADD ECX, EBX ; Add
1959 MOV AX, I_DS ; AX:ESI = source
1960 POP EDI ; Offset
1961 CALL MOVE_TO_RM ; Copy to real-mode buffer
1962 POP AX ; Terminator and flag
1963 CMP AH, FALSE ; Path name?
1964 JE SHORT IDELIM_1 ; No -> return
1965 PUSH ES
1966 MOV ES, BUF_SEL
1967 CALL TRUNCATE
1968 POP ES
1969IDELIM_1: RET
1970
1971IDELIM_2: POP EDI
1972 POP AX
1973 JMP DOSF_PARAM
1974 ASSUME BP:NOTHING
1975I_DELIM ENDP
1976
1977;
1978; Set disk transfer address to OFFSET_1
1979;
1980SET_DTA_1 PROC NEAR
1981 PUSH RM_AX ; Save real-mode AX
1982 PUSH RM_DX ; Save real-mode DX
1983 MOV RM_AX, 1A00H ; Set disk transfer address
1984 MOV RM_DX, OFFSET_1 ; to OFFSET_1
1985 CALL INT_RM ; Call DOS
1986 POP RM_DX ; Restore real-mode DX
1987 POP RM_AX ; Restore real-mode AX
1988 RET
1989SET_DTA_1 ENDP
1990
1991
1992;
1993; Copy protected-mode registers to real-mode registers
1994;
1995 ASSUME DS:SV_DATA
1996 ASSUME BP:PTR ISTACKFRAME
1997 TALIGN 4
1998REGS_TO_RM PROC NEAR
1999 IRP R, <AX,BX,CX,DX,SI,DI,BP>
2000 MOV AX, WORD PTR I_E&R ; Load general real-mode
2001 MOV RM_&R, AX ; registers
2002 ENDM
2003 MOV AX, BUF_SEG ; Load real-mode segment
2004 MOV RM_DS, AX ; registers
2005 MOV RM_ES, AX
2006 RET
2007 ASSUME BP:NOTHING
2008REGS_TO_RM ENDP
2009
2010;
2011; Copy real-mode registers to protected-mode stack frame
2012;
2013 ASSUME DS:SV_DATA
2014 ASSUME BP:PTR ISTACKFRAME
2015 TALIGN 4
2016REGS_FROM_RM PROC NEAR
2017 IRP R, <AX,BX,CX,DX,SI,DI,BP>
2018 MOV AX, RM_&R
2019 MOV WORD PTR I_E&R, AX
2020 ENDM
2021 MOV AL, RM_FLAGS
2022 MOV BYTE PTR I_EFLAGS[0], AL
2023 RET
2024 ASSUME BP:NOTHING
2025REGS_FROM_RM ENDP
2026
2027
2028
2029;
2030; Copy buffer from protected mode to real mode
2031;
2032; In: AX:ESI Source (protected mode)
2033; EDI OFFSET_1 or OFFSET_2
2034; ECX Number of bytes
2035;
2036
2037 ASSUME DS:SV_DATA
2038
2039 TALIGN 4
2040MOVE_TO_RM PROC NEAR PUBLIC
2041 PUSH DS
2042 PUSH ES
2043 PUSH EAX
2044 PUSH ECX
2045 PUSH EDX
2046 PUSH ESI
2047 PUSH EDI
2048 MOV ES, BUF_SEL
2049 MOV DS, AX
2050 ASSUME DS:NOTHING
2051 CLD
2052 MOV EAX, ECX
2053 SHR ECX, 2
2054 REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
2055 MOV ECX, EAX
2056 AND ECX, 3
2057 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
2058 POP EDI
2059 POP ESI
2060 POP EDX
2061 POP ECX
2062 POP EAX
2063 POP ES
2064 POP DS
2065 RET
2066MOVE_TO_RM ENDP
2067
2068
2069;
2070; Copy buffer from real mode to protected mode
2071;
2072; In: AX:EDI Destination address
2073; ECX Number of bytes
2074;
2075; Note: always uses OFFSET_1
2076;
2077
2078 ASSUME DS:SV_DATA
2079
2080MOVE_FROM_RM PROC NEAR PUBLIC
2081 PUSH DS
2082 PUSH ES
2083 PUSH EAX
2084 PUSH ECX
2085 PUSH ESI
2086 PUSH EDI
2087 MOV ES, AX
2088 MOV ESI, OFFSET_1
2089 MOV DS, BUF_SEL
2090 ASSUME DS:NOTHING
2091 CLD
2092 MOV EAX, ECX
2093 SHR ECX, 2
2094 REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
2095 MOV ECX, EAX
2096 AND ECX, 3
2097 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
2098 POP EDI
2099 POP ESI
2100 POP ECX
2101 POP EAX
2102 POP ES
2103 POP DS
2104 RET
2105MOVE_FROM_RM ENDP
2106
2107
2108;
2109; Copy zero-terminated buffer from real mode to protected mode
2110;
2111; In: AX:EDI Destination address
2112;
2113; Note: always uses OFFSET_1
2114;
2115
2116 ASSUME DS:SV_DATA
2117
2118MOVEZ_FROM_RM PROC NEAR
2119 PUSH DS
2120 PUSH ES
2121 PUSH EAX
2122 PUSH ESI
2123 PUSH EDI
2124 MOV ES, AX
2125 MOV ESI, OFFSET_1
2126 MOV DS, BUF_SEL
2127 ASSUME DS:NOTHING
2128 CLD
2129 TALIGN 4
2130MZFRM1: LODS BYTE PTR DS:[ESI]
2131 STOS BYTE PTR ES:[EDI]
2132 TEST AL, AL
2133 JNZ SHORT MZFRM1
2134 POP EDI
2135 POP ESI
2136 POP EAX
2137 POP ES
2138 POP DS
2139 RET
2140MOVEZ_FROM_RM ENDP
2141
2142;
2143; Set a breakpoint to the return address of the current interrupt/exception
2144; frame (only if -S option is used)
2145;
2146 ASSUME DS:SV_DATA
2147 ASSUME BP:PTR ISTACKFRAME
2148 TALIGN 4
2149BREAK_AFTER_IRET PROC NEAR
2150 CMP STEP_FLAG, FALSE
2151 JE SHORT BAI_RET
2152 MOV DX, I_CS
2153 MOV EAX, I_EIP
2154 CALL SET_BREAKPOINT
2155 CALL INS_BREAKPOINTS
2156BAI_RET: RET
2157 ASSUME BP:NOTHING
2158BREAK_AFTER_IRET ENDP
2159
2160
2161;
2162; Set the DBCS lead byte table. This function must be called from PMINT.
2163;
2164; Out: AX Zero if successful, non-zero on error
2165;
2166 ASSUME DS:SV_DATA
2167GET_DBCS_LEAD PROC NEAR
2168;
2169; First clear all bits in case we can't retrieve the DBCS lead bytes
2170;
2171 PUSH DS
2172 POP ES
2173 MOV DI, DBCS_LEAD_TAB
2174 MOV CX, 256 / 8 / 2
2175 MOV AX, 0
2176 REP STOSW
2177;
2178; Call DOS to get the DBCS lead bytes
2179;
2180 MOV RM_AX, 6300H
2181 MOV RM_DS, 0FFFEH
2182 MOV RM_SI, 0FFFFH
2183 CALL INT_RM
2184;
2185; Note that some DOS versions return AL=0 even if this function is
2186; not supported. Do some sanity checking on DS:SI
2187;
2188 CMP BYTE PTR RM_AX[0], 0
2189 JNE SHORT GDL_FAIL
2190 CMP RM_SI, -12
2191 JA SHORT GDL_FAIL
2192 MOV AX, RM_DS
2193 CMP AX, 0FFFEH
2194 JE SHORT GDL_FAIL
2195 SHL EAX, 16
2196 MOV AX, RM_SI
2197 CALL ACCESS_LOWMEM
2198 MOV ESI, EBX
2199 MOV AX, G_LOWMEM_SEL
2200 MOV ES, AX
2201 MOV CX, 6
2202GDL_CHECK1: MOV AX, ES:[EBX]
2203 TEST AX, AX
2204 JZ SHORT GDL_CHECK1_OK
2205 CMP AL, 80H
2206 JB SHORT GDL_FAIL
2207 CMP AL, AH
2208 JA SHORT GDL_FAIL
2209 ADD EBX, 2
2210 LOOP GDL_CHECK1
2211GDL_FAIL: MOV AX, 1
2212 RET
2213
2214;
2215; The table looks OK; now set the bits
2216;
2217GDL_CHECK1_OK: MOV CX, 0
2218GDL_LOOP1: MOV AX, ES:[ESI]
2219 TEST AX, AX
2220 JZ SHORT GDL_DONE
2221 ADD ESI, 2
2222 MOV CL, AL
2223GDL_LOOP2: BTS DBCS_LEAD_TAB, CX
2224 CMP CL, AH
2225 JAE SHORT GDL_LOOP1
2226 INC CL
2227 JMP SHORT GDL_LOOP2
2228
2229GDL_DONE: XOR AX, AX
2230 RET
2231
2232GET_DBCS_LEAD ENDP
2233
2234SV_CODE ENDS
2235
2236
2237;
2238; Yes, this module contains real-mode code.
2239;
2240INIT_CODE SEGMENT
2241
2242 ASSUME CS:INIT_CODE, DS:NOTHING
2243
2244;
2245;
2246;
2247
2248;
2249; Use backward jump to this code for processors with BIG prefetch queue
2250;
2251 TALIGN 4
2252INT_BACK_1: JMPF16 G_SV_CODE_SEL, RM_INT9
2253
2254;
2255; Generic software interrupt without conversion
2256;
2257 ASSUME DS:SV_DATA
2258FLUSH2: CALL GET_REGS ; Load registers from variables
2259 ASSUME DS:NOTHING
2260INT_OP_2 LABEL BYTE
2261 INT 0 ; Call interrupt routine
2262 CALL PUT_REGS ; Store registers to variables
2263 JMP SHORT INT_BACK ; Back to protected mode
2264
2265;
2266; Hardware interrupt
2267;
2268 ASSUME DS:NOTHING
2269 TALIGN 4
2270FLUSH1: PUSH ES
2271 PUSH BP
2272INT_OP_1 LABEL BYTE
2273 INT 0
2274 STI ; Allow interrupts here
2275 POP BP
2276 POP ES
2277 CMP ES:HW_INT_VEC, 01H ; Keyboard interrupt (IRQ1)?
2278 JNE SHORT POSTINT_10
2279 MOV AX, SV_DATA
2280 MOV DS, AX
2281 ASSUME DS:SV_DATA
2282 TEST STDIN_TERMIO.C_LFLAG, IDEFAULT
2283 JNZ SHORT POSTINT_10
2284 TEST STDIN_TERMIO.C_LFLAG, ISIG
2285 JZ SHORT POSTINT_10
2286 CALL POLL_KEYBOARD
2287 ASSUME DS:NOTHING
2288POSTINT_10:
2289;
2290;
2291;
2292 ASSUME DS:NOTHING
2293INT_BACK: MOV AX, SV_DATA
2294 MOV DS, AX
2295 ASSUME DS:SV_DATA
2296 CALL CHECK_A20 ; A20 enabled?
2297 TEST AX, AX
2298 JNZ SHORT INT_BACK_GO ; Yes -> skip
2299 CALL A20_ON ; Enable A20
2300INT_BACK_GO: CLI
2301 CMP VCPI_FLAG, FALSE ; VCPI?
2302 JNE INT_BACK_VCPI ; Yes -> use server
2303 LGDT GDT_PTR
2304 LIDT IDT_PTR
2305 MOV EAX, CR0
2306 OR EAX, CR0_PE ; Enable protected mode
2307 MOV CR0, EAX
2308 JMP INT_BACK_1 ; Flush prefetch queue
2309
2310
2311 TALIGN 4
2312RM_INT2 LABEL FAR
2313 MOV AX, SV_DATA
2314 MOV DS, AX
2315 ASSUME DS:SV_DATA
2316 MOV FS, AX
2317 MOV GS, AX
2318 MOV AX, RM_STACK
2319 MOV SS, AX
2320 LEA SP, RM_TOS
2321 LIDT REAL_IDT_PTR
2322;
2323; Entrypoint from VCPI server
2324;
2325V2V_CONT: MOV BP, FRAME_PTR ; Access registers of prot mode
2326 MOV AX, SV_STACK
2327 MOV ES, AX
2328 CMP MACHINE, MACH_PC ; PC?
2329 JE SHORT INT_BEG_1 ; Yes -> keep A20 enabled
2330 CMP MACHINE, MACH_INBOARD ; Inboard 386/PC?
2331 JE SHORT INT_BEG_1 ; Yes -> keep A20 enabled
2332 CALL A20_OFF ; No -> disable A20
2333INT_BEG_1: MOV AL, ES:INT_NO ; Uses BP!
2334 CMP AL, 10H
2335 JE VIO_INT
2336 CMP AL, 11H
2337 JE SOFTWARE_INT
2338 CMP AL, 14H
2339 JE SOFTWARE_INT
2340 CMP AL, 16H
2341 JE SOFTWARE_INT
2342 CMP AL, 17H
2343 JE SOFTWARE_INT
2344 CMP AL, 21H
2345 JE SHORT DOS_INT
2346 CMP AL, 33H
2347 JE SOFTWARE_INT
2348 MOV CS:INT_OP_1+1, AL ; Self-modifying code,
2349 JMP FLUSH1 ; flush prefetch queue!
2350
2351
2352
2353 ASSUME DS:SV_DATA
2354
2355 TALIGN 4
2356DOS_INT: STI ; Enable interrupts
2357 MOV AX, ES:RM_AX
2358 CMP AX, 7F16H ; Poll keyboard?
2359 JE SHORT DOS_INT_PK
2360 CMP AX, 7F2AH ; __nls_memupr()?
2361 JE SHORT DOS_INT_MEMUPR
2362 PUSH AX
2363 CMP AH, 4BH ; Exec?
2364 JNE SHORT DOS_INT_1
2365 PUSH ES
2366 CALL CLEANUP_INT ; Cleanup interrupts
2367 POP ES
2368DOS_INT_1: CALL GET_REGS ; Load registers from variables
2369 ASSUME DS:NOTHING
2370 CMP AH, 4CH ; Terminate process?
2371 JE EXIT ; Yes ->
2372 INT 21H
2373 CALL PUT_REGS
2374 POP AX
2375 CMP AH, 4BH ; Exec?
2376 JNE SHORT DOS_INT_2
2377 CALL INIT_INT ; Reinitialize interrupts
2378DOS_INT_2: JMP INT_BACK
2379
2380
2381DOS_INT_PK: CALL POLL_KEYBOARD
2382 JMP SHORT DOS_INT_2
2383
2384;
2385; Real-mode part of __nls_memupr()
2386;
2387 ASSUME DS:SV_DATA
2388
2389DOS_INT_MEMUPR: CMP ES:RM_CX, 0
2390 JE SHORT DOS_INT_2
2391 LEA DX, COUNTRYDATA
2392 MOV AX, 3800H
2393 INT 21H
2394 JC SHORT DOS_INT_2
2395 MOV BX, ES:RM_DX
2396 MOV CX, ES:RM_CX
2397 MOV ES, BUF_SEG
2398MEMUPR_LOOP: MOV AL, ES:[BX]
2399 TEST AL, AL
2400 JS SHORT MEMUPR_HIGH
2401 CMP AL, "a"
2402 JB SHORT MEMUPR_NEXT
2403 CMP AL, "z"
2404 JA SHORT MEMUPR_NEXT
2405 SUB AL, "a" - "A"
2406MEMUPR_STORE: MOV ES:[BX], AL
2407MEMUPR_NEXT: INC BX
2408 LOOP MEMUPR_LOOP
2409 JMP SHORT DOS_INT_2
2410
2411MEMUPR_HIGH: CALL CD_CASEMAP
2412 JMP SHORT MEMUPR_STORE
2413
2414;
2415; Software interrupt 10H
2416;
2417 ASSUME DS:SV_DATA
2418 TALIGN 4
2419VIO_INT: STI ; Enable interrupts
2420 CALL GET_REGS ; Load registers from variables
2421 ASSUME DS:NOTHING
2422 PUSH AX ; Save AH (function number)
2423 INT 10H ; Call BIOS
2424 CALL PUT_REGS ; Store registers to variables
2425 POP AX ; Restore AH (function number)
2426 CMP AH, 00H ; Set mode?
2427 JNE INT_BACK ; No -> back to protected mode
2428 CALL VINIT ; Get new width and height
2429 JMP INT_BACK ; Back to protected mode
2430
2431;
2432; Generic software interrupt
2433;
2434 ASSUME DS:SV_DATA
2435 TALIGN 4
2436SOFTWARE_INT: STI ; Enable interrupts
2437 MOV CS:INT_OP_2+1, AL ; Self-modifying code,
2438 JMP FLUSH2 ; flush prefetch queue!
2439
2440
2441;
2442; Load registers from variables
2443;
2444; Attention: ES:BP points to protected mode stack frame!
2445;
2446 ASSUME DS:NOTHING
2447 TALIGN 4
2448GET_REGS PROC NEAR
2449 MOV AX, ES:RM_AX
2450 MOV BX, ES:RM_BX
2451 MOV CX, ES:RM_CX
2452 MOV DX, ES:RM_DX
2453 MOV SI, ES:RM_SI
2454 MOV DI, ES:RM_DI
2455 MOV DS, ES:RM_DS
2456 PUSH ES:RM_BP
2457 MOV ES, ES:RM_ES
2458 POP BP
2459 RET
2460GET_REGS ENDP
2461
2462
2463;
2464; Has to load ES:BP with address of protected-mode stack frame!
2465;
2466 ASSUME DS:NOTHING
2467 TALIGN 4
2468PUT_REGS PROC NEAR
2469 PUSH DS
2470 PUSH ES
2471 PUSH BP
2472 PUSH AX
2473 MOV AX, SV_DATA
2474 MOV DS, AX
2475 ASSUME DS:SV_DATA
2476 MOV AX, SV_STACK
2477 MOV ES, AX
2478 MOV BP, FRAME_PTR
2479 LAHF
2480 MOV ES:RM_FLAGS, AH
2481 POP ES:RM_AX
2482 POP ES:RM_BP
2483 POP ES:RM_ES
2484 POP ES:RM_DS
2485 MOV ES:RM_BX, BX
2486 MOV ES:RM_CX, CX
2487 MOV ES:RM_DX, DX
2488 MOV ES:RM_SI, SI
2489 MOV ES:RM_DI, DI
2490 RET
2491PUT_REGS ENDP
2492
2493
2494
2495;
2496; Allocate buffers for real-mode interface.
2497;
2498; We need two buffers:
2499;
2500; - the first buffer is used for the user program's i/o
2501;
2502; - the second buffer is used for the swapper's i/o. The swapper
2503; may be activated while copying the user program's i/o buffer
2504;
2505; The two buffers have there own selectors (and GDT entries)
2506;
2507
2508 ASSUME DS:SV_DATA
2509INIT_BUFFER PROC NEAR
2510 MOV BX, 1000H ; 64 KB
2511 LEA DI, G_BUF1_DESC
2512 CALL INIT_BUF_1
2513 MOV BUF1_SEG, AX ; Main buffer segment
2514 MOV BX, 0101H ; 4 KB + 16 Bytes
2515 LEA DI, G_BUF2_DESC
2516 CALL INIT_BUF_1
2517 MOV BUF2_SEG, AX ; Swapper buffer segment
2518;
2519; Select 1st buffer (64KB)
2520;
2521 MOV AX, BUF1_SEG
2522 MOV BUF_SEG, AX
2523 MOV BUF_SEL, G_BUF1_SEL
2524 RET
2525
2526
2527INIT_BUF_1 PROC NEAR
2528 MOV AH, 48H
2529 INT 21H
2530 JC RM_OUT_OF_MEM
2531 PUSH AX
2532 MOVZX EAX, AX
2533 SHL EAX, 4
2534 CALL RM_SEG_BASE
2535 POP AX
2536 RET
2537INIT_BUF_1 ENDP
2538
2539INIT_BUFFER ENDP
2540
2541
2542 IF DEBUG_DOSDUMP
2543
2544 ASSUME DS:NOTHING
2545DOSDUMP PROC NEAR
2546 PUSHAD
2547 PUSH DS
2548 PUSH ES
2549 MOV AX, SV_DATA
2550 MOV DS, AX
2551 ASSUME DS:SV_DATA
2552 LEA BX, $DOSDUMP_C
2553DOSDUMP_10: MOV AL, [BX]
2554 INC BYTE PTR [BX]
2555 CMP AL, "9"
2556 JNE SHORT DOSDUMP_11
2557 MOV BYTE PTR [BX], "0"
2558 DEC BX
2559 JMP SHORT DOSDUMP_10
2560
2561DOSDUMP_11: LEA DX, $DOSDUMP
2562 MOV CX, 0
2563 MOV AH, 3CH
2564 INT 21H
2565 JC SHORT DOSDUMP_ERR
2566 MOV BX, AX
2567 MOV CX, 640 / 32
2568 MOV SI, 0
2569DOSDUMP_20: PUSH CX
2570 PUSH DS
2571 MOV DS, SI
2572 ASSUME DS:NOTHING
2573 MOV DX, 0
2574 MOV CX, 32 * 1024
2575 MOV AH, 40H
2576 INT 21H
2577 POP DS
2578 ASSUME DS:SV_DATA
2579 POP CX
2580 JC SHORT DOSDUMP_ERR
2581 ADD SI, 32 * 1024 / 16
2582 LOOP DOSDUMP_20
2583 MOV AH, 3EH
2584 INT 21H
2585 JMP SHORT DOSDUMP_RET
2586
2587DOSDUMP_ERR:
2588DOSDUMP_RET: POP ES
2589 POP DS
2590 POPAD
2591 RET
2592DOSDUMP ENDP
2593
2594 ENDIF
2595
2596
2597INIT_CODE ENDS
2598
2599 END
Note: See TracBrowser for help on using the repository browser.