2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/io.c
5 * PURPOSE: I/O Port Handlers
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
20 /* PRIVATE VARIABLES **********************************************************/
22 typedef struct _EMULATOR_IO_HANDLERS
24 EMULATOR_INB_PROC InB
;
25 EMULATOR_INW_PROC InW
;
26 EMULATOR_IND_PROC InD
;
28 EMULATOR_INSB_PROC InsB
;
29 EMULATOR_INSW_PROC InsW
;
30 EMULATOR_INSD_PROC InsD
;
32 EMULATOR_OUTB_PROC OutB
;
33 EMULATOR_OUTW_PROC OutW
;
34 EMULATOR_OUTD_PROC OutD
;
36 EMULATOR_OUTSB_PROC OutsB
;
37 EMULATOR_OUTSW_PROC OutsW
;
38 EMULATOR_OUTSD_PROC OutsD
;
39 } EMULATOR_IO_HANDLERS
, *PEMULATOR_IO_HANDLERS
;
41 typedef struct _EMULATOR_IOPORT_HANDLERS
43 HANDLE hVdd
; // == NULL if unused,
44 // INVALID_HANDLE_VALUE if handled internally,
45 // a valid VDD handle if handled externally.
48 /* For Windows compatibility only, not used internally... */
49 VDD_IO_HANDLERS VddIoHandlers
;
51 /* ... we use these members internally */
52 EMULATOR_IO_HANDLERS IoHandlers
;
54 } EMULATOR_IOPORT_HANDLERS
, *PEMULATOR_IOPORT_HANDLERS
;
57 * This is the list of registered I/O Port handlers.
59 EMULATOR_IOPORT_HANDLERS IoPortProc
[EMULATOR_MAX_IOPORTS_NUM
] = {{NULL
}};
61 /* PUBLIC FUNCTIONS ***********************************************************/
66 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
67 IoPortProc
[Port
].IoHandlers
.InB
)
69 return IoPortProc
[Port
].IoHandlers
.InB(Port
);
71 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
72 IoPortProc
[Port
].VddIoHandlers
.inb_handler
)
75 ASSERT(Port
<= MAXWORD
);
76 IoPortProc
[Port
].VddIoHandlers
.inb_handler(Port
, &Data
);
81 /* Return an empty port byte value */
82 DPRINT("Read from unknown port: 0x%X\n", Port
);
88 IOReadStrB(USHORT Port
,
92 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
93 IoPortProc
[Port
].IoHandlers
.InsB
)
95 IoPortProc
[Port
].IoHandlers
.InsB(Port
, Buffer
, Count
);
97 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
98 IoPortProc
[Port
].VddIoHandlers
.insb_handler
)
100 ASSERT(Port
<= MAXWORD
);
101 ASSERT(Count
<= MAXWORD
);
102 IoPortProc
[Port
].VddIoHandlers
.insb_handler(Port
, Buffer
, (WORD
)Count
);
106 while (Count
--) *Buffer
++ = IOReadB(Port
);
111 IOWriteB(USHORT Port
,
114 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
115 IoPortProc
[Port
].IoHandlers
.OutB
)
117 IoPortProc
[Port
].IoHandlers
.OutB(Port
, Buffer
);
119 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
120 IoPortProc
[Port
].VddIoHandlers
.outb_handler
)
122 ASSERT(Port
<= MAXWORD
);
123 IoPortProc
[Port
].VddIoHandlers
.outb_handler(Port
, Buffer
);
128 DPRINT("Write to unknown port: 0x%X\n", Port
);
133 IOWriteStrB(USHORT Port
,
137 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
138 IoPortProc
[Port
].IoHandlers
.OutsB
)
140 IoPortProc
[Port
].IoHandlers
.OutsB(Port
, Buffer
, Count
);
142 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
143 IoPortProc
[Port
].VddIoHandlers
.outsb_handler
)
145 ASSERT(Port
<= MAXWORD
);
146 ASSERT(Count
<= MAXWORD
);
147 IoPortProc
[Port
].VddIoHandlers
.outsb_handler(Port
, Buffer
, (WORD
)Count
);
151 while (Count
--) IOWriteB(Port
, *Buffer
++);
158 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
159 IoPortProc
[Port
].IoHandlers
.InW
)
161 return IoPortProc
[Port
].IoHandlers
.InW(Port
);
163 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
164 IoPortProc
[Port
].VddIoHandlers
.inw_handler
)
167 ASSERT(Port
<= MAXWORD
);
168 IoPortProc
[Port
].VddIoHandlers
.inw_handler(Port
, &Data
);
175 // FIXME: Is it ok on Little endian and Big endian ??
177 High
= IOReadB(Port
+ sizeof(UCHAR
));
178 return MAKEWORD(Low
, High
);
183 IOReadStrW(USHORT Port
,
187 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
188 IoPortProc
[Port
].IoHandlers
.InsW
)
190 IoPortProc
[Port
].IoHandlers
.InsW(Port
, Buffer
, Count
);
192 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
193 IoPortProc
[Port
].VddIoHandlers
.insw_handler
)
195 ASSERT(Port
<= MAXWORD
);
196 ASSERT(Count
<= MAXWORD
);
197 IoPortProc
[Port
].VddIoHandlers
.insw_handler(Port
, Buffer
, (WORD
)Count
);
201 while (Count
--) *Buffer
++ = IOReadW(Port
);
206 IOWriteW(USHORT Port
,
209 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
210 IoPortProc
[Port
].IoHandlers
.OutW
)
212 IoPortProc
[Port
].IoHandlers
.OutW(Port
, Buffer
);
214 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
215 IoPortProc
[Port
].VddIoHandlers
.outw_handler
)
217 ASSERT(Port
<= MAXWORD
);
218 IoPortProc
[Port
].VddIoHandlers
.outw_handler(Port
, Buffer
);
222 // FIXME: Is it ok on Little endian and Big endian ??
223 IOWriteB(Port
, LOBYTE(Buffer
));
224 IOWriteB(Port
+ sizeof(UCHAR
), HIBYTE(Buffer
));
229 IOWriteStrW(USHORT Port
,
233 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
234 IoPortProc
[Port
].IoHandlers
.OutsW
)
236 IoPortProc
[Port
].IoHandlers
.OutsW(Port
, Buffer
, Count
);
238 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
239 IoPortProc
[Port
].VddIoHandlers
.outsw_handler
)
241 ASSERT(Port
<= MAXWORD
);
242 ASSERT(Count
<= MAXWORD
);
243 IoPortProc
[Port
].VddIoHandlers
.outsw_handler(Port
, Buffer
, (WORD
)Count
);
247 while (Count
--) IOWriteW(Port
, *Buffer
++);
254 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
255 IoPortProc
[Port
].IoHandlers
.InD
)
257 return IoPortProc
[Port
].IoHandlers
.InD(Port
);
263 // FIXME: Is it ok on Little endian and Big endian ??
265 High
= IOReadW(Port
+ sizeof(USHORT
));
266 return MAKELONG(Low
, High
);
271 IOReadStrD(USHORT Port
,
275 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
276 IoPortProc
[Port
].IoHandlers
.InsD
)
278 IoPortProc
[Port
].IoHandlers
.InsD(Port
, Buffer
, Count
);
282 while (Count
--) *Buffer
++ = IOReadD(Port
);
287 IOWriteD(USHORT Port
,
290 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
291 IoPortProc
[Port
].IoHandlers
.OutD
)
293 IoPortProc
[Port
].IoHandlers
.OutD(Port
, Buffer
);
297 // FIXME: Is it ok on Little endian and Big endian ??
298 IOWriteW(Port
, LOWORD(Buffer
));
299 IOWriteW(Port
+ sizeof(USHORT
), HIWORD(Buffer
));
304 IOWriteStrD(USHORT Port
,
308 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
309 IoPortProc
[Port
].IoHandlers
.OutsD
)
311 IoPortProc
[Port
].IoHandlers
.OutsD(Port
, Buffer
, Count
);
315 while (Count
--) IOWriteD(Port
, *Buffer
++);
320 VOID
RegisterIoPort(USHORT Port
,
321 EMULATOR_INB_PROC InHandler
,
322 EMULATOR_OUTB_PROC OutHandler
)
324 if (IoPortProc
[Port
].IoHandlers
.InB
== NULL
)
325 IoPortProc
[Port
].IoHandlers
.InB
= InHandler
;
327 DPRINT1("IoPortProc[0x%X].IoHandlers.InB already registered\n", Port
);
329 if (IoPortProc
[Port
].IoHandlers
.OutB
== NULL
)
330 IoPortProc
[Port
].IoHandlers
.OutB
= OutHandler
;
332 DPRINT1("IoPortProc[0x%X].IoHandlers.OutB already registered\n", Port
);
334 /* We hold the I/O port internally */
335 IoPortProc
[Port
].hVdd
= INVALID_HANDLE_VALUE
;
338 VOID
UnregisterIoPort(USHORT Port
)
341 * Put automagically all the fields to zero:
342 * the hVdd gets unregistered as well as all the handlers.
344 // IoPortProc[Port] = {NULL};
345 RtlZeroMemory(&IoPortProc
[Port
], sizeof(IoPortProc
[Port
]));
349 EmulatorReadIo(PFAST486_STATE State
,
355 UNREFERENCED_PARAMETER(State
);
357 if (DataSize
== 0 || DataCount
== 0) return;
359 if (DataSize
== sizeof(UCHAR
))
362 *(PUCHAR
)Buffer
= IOReadB(Port
);
364 IOReadStrB(Port
, Buffer
, DataCount
);
366 else if (DataSize
== sizeof(USHORT
))
369 *(PUSHORT
)Buffer
= IOReadW(Port
);
371 IOReadStrW(Port
, Buffer
, DataCount
);
373 else if (DataSize
== sizeof(ULONG
))
376 *(PULONG
)Buffer
= IOReadD(Port
);
378 IOReadStrD(Port
, Buffer
, DataCount
);
382 PUCHAR Address
= (PUCHAR
)Buffer
;
386 ULONG CurrentPort
= Port
;
388 UCHAR NewDataSize
= DataSize
;
391 Count
= NewDataSize
>> 2; // NewDataSize / sizeof(ULONG);
392 NewDataSize
= NewDataSize
& 3; // NewDataSize % sizeof(ULONG);
395 *(PULONG
)Address
= IOReadD(CurrentPort
);
396 CurrentPort
+= sizeof(ULONG
);
397 Address
+= sizeof(ULONG
);
401 Count
= NewDataSize
>> 1; // NewDataSize / sizeof(USHORT);
402 NewDataSize
= NewDataSize
& 1; // NewDataSize % sizeof(USHORT);
405 *(PUSHORT
)Address
= IOReadW(CurrentPort
);
406 CurrentPort
+= sizeof(USHORT
);
407 Address
+= sizeof(USHORT
);
411 Count
= NewDataSize
; // NewDataSize / sizeof(UCHAR);
412 // NewDataSize = NewDataSize % sizeof(UCHAR);
415 *(PUCHAR
)Address
= IOReadB(CurrentPort
);
416 CurrentPort
+= sizeof(UCHAR
);
417 Address
+= sizeof(UCHAR
);
424 EmulatorWriteIo(PFAST486_STATE State
,
430 UNREFERENCED_PARAMETER(State
);
432 if (DataSize
== 0 || DataCount
== 0) return;
434 if (DataSize
== sizeof(UCHAR
))
437 IOWriteB(Port
, *(PUCHAR
)Buffer
);
439 IOWriteStrB(Port
, Buffer
, DataCount
);
441 else if (DataSize
== sizeof(USHORT
))
444 IOWriteW(Port
, *(PUSHORT
)Buffer
);
446 IOWriteStrW(Port
, Buffer
, DataCount
);
448 else if (DataSize
== sizeof(ULONG
))
451 IOWriteD(Port
, *(PULONG
)Buffer
);
453 IOWriteStrD(Port
, Buffer
, DataCount
);
457 PUCHAR Address
= (PUCHAR
)Buffer
;
461 ULONG CurrentPort
= Port
;
463 UCHAR NewDataSize
= DataSize
;
466 Count
= NewDataSize
>> 2; // NewDataSize / sizeof(ULONG);
467 NewDataSize
= NewDataSize
& 3; // NewDataSize % sizeof(ULONG);
470 IOWriteD(CurrentPort
, *(PULONG
)Address
);
471 CurrentPort
+= sizeof(ULONG
);
472 Address
+= sizeof(ULONG
);
476 Count
= NewDataSize
>> 1; // NewDataSize / sizeof(USHORT);
477 NewDataSize
= NewDataSize
& 1; // NewDataSize % sizeof(USHORT);
480 IOWriteW(CurrentPort
, *(PUSHORT
)Address
);
481 CurrentPort
+= sizeof(USHORT
);
482 Address
+= sizeof(USHORT
);
486 Count
= NewDataSize
; // NewDataSize / sizeof(UCHAR);
487 // NewDataSize = NewDataSize % sizeof(UCHAR);
490 IOWriteB(CurrentPort
, *(PUCHAR
)Address
);
491 CurrentPort
+= sizeof(UCHAR
);
492 Address
+= sizeof(UCHAR
);
502 VDDInstallIOHook(IN HANDLE hVdd
,
504 IN PVDD_IO_PORTRANGE pPortRange
,
505 IN PVDD_IO_HANDLERS IoHandlers
)
509 /* Check validity of the VDD handle */
510 if (hVdd
== NULL
|| hVdd
== INVALID_HANDLE_VALUE
)
512 SetLastError(ERROR_INVALID_PARAMETER
);
516 /* Loop for each range of I/O ports */
519 /* Register the range of I/O ports */
520 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
523 * Don't do anything if the I/O port is already
524 * handled internally or externally.
526 if (IoPortProc
[i
].hVdd
!= NULL
)
528 DPRINT1("IoPortProc[0x%X] already registered\n", i
);
532 /* Register wrt. the VDD */
533 IoPortProc
[i
].hVdd
= hVdd
;
535 /* Disable the internal handlers */
536 IoPortProc
[i
].IoHandlers
.InB
= NULL
;
537 IoPortProc
[i
].IoHandlers
.InW
= NULL
;
538 IoPortProc
[i
].IoHandlers
.InD
= NULL
;
540 IoPortProc
[i
].IoHandlers
.InsB
= NULL
;
541 IoPortProc
[i
].IoHandlers
.InsW
= NULL
;
542 IoPortProc
[i
].IoHandlers
.InsD
= NULL
;
544 IoPortProc
[i
].IoHandlers
.OutB
= NULL
;
545 IoPortProc
[i
].IoHandlers
.OutW
= NULL
;
546 IoPortProc
[i
].IoHandlers
.OutD
= NULL
;
548 IoPortProc
[i
].IoHandlers
.OutsB
= NULL
;
549 IoPortProc
[i
].IoHandlers
.OutsW
= NULL
;
550 IoPortProc
[i
].IoHandlers
.OutsD
= NULL
;
552 /* Save our handlers */
553 IoPortProc
[i
].VddIoHandlers
= *IoHandlers
;
556 /* Go to the next range */
565 VDDDeInstallIOHook(IN HANDLE hVdd
,
567 IN PVDD_IO_PORTRANGE pPortRange
)
571 /* Check validity of the VDD handle */
572 if (hVdd
== NULL
|| hVdd
== INVALID_HANDLE_VALUE
)
574 SetLastError(ERROR_INVALID_PARAMETER
);
578 /* Loop for each range of I/O ports */
581 /* Unregister the range of I/O ports */
582 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
585 * Don't do anything if we don't own the I/O port.
587 if (IoPortProc
[i
].hVdd
!= hVdd
)
589 DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i
);
594 * Put automagically all the fields to zero:
595 * the hVdd gets unregistered as well as all the handlers.
597 // IoPortProc[i] = {NULL};
598 RtlZeroMemory(&IoPortProc
[i
], sizeof(IoPortProc
[i
]));
601 /* Go to the next range */