2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
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 *******************************************************************/
17 /* PRIVATE VARIABLES **********************************************************/
19 typedef struct _EMULATOR_IO_HANDLERS
21 EMULATOR_INB_PROC InB
;
22 EMULATOR_INW_PROC InW
;
23 EMULATOR_IND_PROC InD
;
25 EMULATOR_INSB_PROC InsB
;
26 EMULATOR_INSW_PROC InsW
;
27 EMULATOR_INSD_PROC InsD
;
29 EMULATOR_OUTB_PROC OutB
;
30 EMULATOR_OUTW_PROC OutW
;
31 EMULATOR_OUTD_PROC OutD
;
33 EMULATOR_OUTSB_PROC OutsB
;
34 EMULATOR_OUTSW_PROC OutsW
;
35 EMULATOR_OUTSD_PROC OutsD
;
36 } EMULATOR_IO_HANDLERS
, *PEMULATOR_IO_HANDLERS
;
38 typedef struct _EMULATOR_IOPORT_HANDLERS
40 HANDLE hVdd
; // == 0 if unused,
41 // INVALID_HANDLE_VALUE if handled internally,
42 // a valid VDD handle if handled externally.
45 /* For Windows compatibility only, not used internally... */
46 VDD_IO_HANDLERS VddIoHandlers
;
48 /* ... we use these members internally */
49 EMULATOR_IO_HANDLERS IoHandlers
;
51 } EMULATOR_IOPORT_HANDLERS
, *PEMULATOR_IOPORT_HANDLERS
;
54 * This is the list of registered I/O Port handlers.
56 EMULATOR_IOPORT_HANDLERS IoPortProc
[EMULATOR_MAX_IOPORTS_NUM
] = {{NULL
}};
58 /* PRIVATE FUNCTIONS **********************************************************/
64 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
65 IoPortProc
[Port
].IoHandlers
.InB
)
67 *Buffer
= IoPortProc
[Port
].IoHandlers
.InB(Port
);
69 else if (IoPortProc
[Port
].hVdd
> 0 &&
70 IoPortProc
[Port
].VddIoHandlers
.inb_handler
)
72 ASSERT(Port
<= MAXWORD
);
73 IoPortProc
[Port
].VddIoHandlers
.inb_handler((WORD
)Port
, Buffer
);
77 /* Return an empty port byte value */
78 DPRINT("Read from unknown port: 0x%X\n", Port
);
84 IOReadStrB(ULONG Port
,
88 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
89 IoPortProc
[Port
].IoHandlers
.InsB
)
91 IoPortProc
[Port
].IoHandlers
.InsB(Port
, Buffer
, Count
);
93 else if (IoPortProc
[Port
].hVdd
> 0 &&
94 IoPortProc
[Port
].VddIoHandlers
.insb_handler
)
96 ASSERT(Port
<= MAXWORD
);
97 ASSERT(Count
<= MAXWORD
);
98 IoPortProc
[Port
].VddIoHandlers
.insb_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
102 while (Count
--) IOReadB(Port
, Buffer
++);
110 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
111 IoPortProc
[Port
].IoHandlers
.OutB
)
113 IoPortProc
[Port
].IoHandlers
.OutB(Port
, *Buffer
);
115 else if (IoPortProc
[Port
].hVdd
> 0 &&
116 IoPortProc
[Port
].VddIoHandlers
.outb_handler
)
118 ASSERT(Port
<= MAXWORD
);
119 IoPortProc
[Port
].VddIoHandlers
.outb_handler((WORD
)Port
, *Buffer
);
124 DPRINT("Write to unknown port: 0x%X\n", Port
);
129 IOWriteStrB(ULONG Port
,
133 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
134 IoPortProc
[Port
].IoHandlers
.OutsB
)
136 IoPortProc
[Port
].IoHandlers
.OutsB(Port
, Buffer
, Count
);
138 else if (IoPortProc
[Port
].hVdd
> 0 &&
139 IoPortProc
[Port
].VddIoHandlers
.outsb_handler
)
141 ASSERT(Port
<= MAXWORD
);
142 ASSERT(Count
<= MAXWORD
);
143 IoPortProc
[Port
].VddIoHandlers
.outsb_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
147 while (Count
--) IOWriteB(Port
, Buffer
++);
155 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
156 IoPortProc
[Port
].IoHandlers
.InW
)
158 *Buffer
= IoPortProc
[Port
].IoHandlers
.InW(Port
);
160 else if (IoPortProc
[Port
].hVdd
> 0 &&
161 IoPortProc
[Port
].VddIoHandlers
.inw_handler
)
163 ASSERT(Port
<= MAXWORD
);
164 IoPortProc
[Port
].VddIoHandlers
.inw_handler((WORD
)Port
, Buffer
);
170 // FIXME: Is it ok on Little endian and Big endian ??
172 IOReadB(Port
+ sizeof(UCHAR
), &High
);
173 *Buffer
= MAKEWORD(Low
, High
);
178 IOReadStrW(ULONG Port
,
182 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
183 IoPortProc
[Port
].IoHandlers
.InsW
)
185 IoPortProc
[Port
].IoHandlers
.InsW(Port
, Buffer
, Count
);
187 else if (IoPortProc
[Port
].hVdd
> 0 &&
188 IoPortProc
[Port
].VddIoHandlers
.insw_handler
)
190 ASSERT(Port
<= MAXWORD
);
191 ASSERT(Count
<= MAXWORD
);
192 IoPortProc
[Port
].VddIoHandlers
.insw_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
196 while (Count
--) IOReadW(Port
, Buffer
++);
204 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
205 IoPortProc
[Port
].IoHandlers
.OutW
)
207 IoPortProc
[Port
].IoHandlers
.OutW(Port
, *Buffer
);
209 else if (IoPortProc
[Port
].hVdd
> 0 &&
210 IoPortProc
[Port
].VddIoHandlers
.outw_handler
)
212 ASSERT(Port
<= MAXWORD
);
213 IoPortProc
[Port
].VddIoHandlers
.outw_handler((WORD
)Port
, *Buffer
);
219 // FIXME: Is it ok on Little endian and Big endian ??
220 Low
= LOBYTE(*Buffer
);
221 High
= HIBYTE(*Buffer
);
222 IOWriteB(Port
, &Low
);
223 IOWriteB(Port
+ sizeof(UCHAR
), &High
);
228 IOWriteStrW(ULONG Port
,
232 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
233 IoPortProc
[Port
].IoHandlers
.OutsW
)
235 IoPortProc
[Port
].IoHandlers
.OutsW(Port
, Buffer
, Count
);
237 else if (IoPortProc
[Port
].hVdd
> 0 &&
238 IoPortProc
[Port
].VddIoHandlers
.outsw_handler
)
240 ASSERT(Port
<= MAXWORD
);
241 ASSERT(Count
<= MAXWORD
);
242 IoPortProc
[Port
].VddIoHandlers
.outsw_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
246 while (Count
--) IOWriteW(Port
, Buffer
++);
254 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
255 IoPortProc
[Port
].IoHandlers
.InD
)
257 *Buffer
= IoPortProc
[Port
].IoHandlers
.InD(Port
);
263 // FIXME: Is it ok on Little endian and Big endian ??
265 IOReadW(Port
+ sizeof(USHORT
), &High
);
266 *Buffer
= MAKELONG(Low
, High
);
271 IOReadStrD(ULONG 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
--) IOReadD(Port
, Buffer
++);
290 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
291 IoPortProc
[Port
].IoHandlers
.OutD
)
293 IoPortProc
[Port
].IoHandlers
.OutD(Port
, *Buffer
);
299 // FIXME: Is it ok on Little endian and Big endian ??
300 Low
= LOWORD(*Buffer
);
301 High
= HIWORD(*Buffer
);
302 IOWriteW(Port
, &Low
);
303 IOWriteW(Port
+ sizeof(USHORT
), &High
);
308 IOWriteStrD(ULONG Port
,
312 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
313 IoPortProc
[Port
].IoHandlers
.OutsD
)
315 IoPortProc
[Port
].IoHandlers
.OutsD(Port
, Buffer
, Count
);
319 while (Count
--) IOWriteD(Port
, Buffer
++);
323 /* PUBLIC FUNCTIONS ***********************************************************/
325 VOID
RegisterIoPort(ULONG Port
,
326 EMULATOR_INB_PROC InHandler
,
327 EMULATOR_OUTB_PROC OutHandler
)
329 if (IoPortProc
[Port
].IoHandlers
.InB
== NULL
)
330 IoPortProc
[Port
].IoHandlers
.InB
= InHandler
;
332 DPRINT1("IoPortProc[0x%X].IoHandlers.InB already registered\n", Port
);
334 if (IoPortProc
[Port
].IoHandlers
.OutB
== NULL
)
335 IoPortProc
[Port
].IoHandlers
.OutB
= OutHandler
;
337 DPRINT1("IoPortProc[0x%X].IoHandlers.OutB already registered\n", Port
);
339 /* We hold the I/O port internally */
340 IoPortProc
[Port
].hVdd
= INVALID_HANDLE_VALUE
;
343 VOID
UnregisterIoPort(ULONG Port
)
346 * Put automagically all the fields to zero:
347 * the hVdd gets unregistered as well as all the handlers.
349 // IoPortProc[Port] = {NULL};
350 ZeroMemory(&IoPortProc
[Port
], sizeof(IoPortProc
[Port
]));
354 EmulatorReadIo(PFAST486_STATE State
,
360 UNREFERENCED_PARAMETER(State
);
362 if (DataSize
== 0 || DataCount
== 0) return;
364 if (DataSize
== sizeof(UCHAR
))
367 IOReadB(Port
, Buffer
);
369 IOReadStrB(Port
, Buffer
, DataCount
);
371 else if (DataSize
== sizeof(USHORT
))
374 IOReadW(Port
, Buffer
);
376 IOReadStrW(Port
, Buffer
, DataCount
);
378 else if (DataSize
== sizeof(ULONG
))
381 IOReadD(Port
, Buffer
);
383 IOReadStrD(Port
, Buffer
, DataCount
);
387 PBYTE Address
= (PBYTE
)Buffer
;
391 ULONG CurrentPort
= Port
;
393 UCHAR NewDataSize
= DataSize
;
396 Count
= NewDataSize
/ sizeof(ULONG
);
397 NewDataSize
= NewDataSize
% sizeof(ULONG
);
400 IOReadD(CurrentPort
, (PULONG
)Address
);
401 CurrentPort
+= sizeof(ULONG
);
402 Address
+= sizeof(ULONG
);
406 Count
= NewDataSize
/ sizeof(USHORT
);
407 NewDataSize
= NewDataSize
% sizeof(USHORT
);
410 IOReadW(CurrentPort
, (PUSHORT
)Address
);
411 CurrentPort
+= sizeof(USHORT
);
412 Address
+= sizeof(USHORT
);
416 Count
= NewDataSize
/ sizeof(UCHAR
);
417 NewDataSize
= NewDataSize
% sizeof(UCHAR
);
420 IOReadB(CurrentPort
, (PUCHAR
)Address
);
421 CurrentPort
+= sizeof(UCHAR
);
422 Address
+= sizeof(UCHAR
);
426 ASSERT(NewDataSize
== 0);
432 EmulatorWriteIo(PFAST486_STATE State
,
438 UNREFERENCED_PARAMETER(State
);
440 if (DataSize
== 0 || DataCount
== 0) return;
442 if (DataSize
== sizeof(UCHAR
))
445 IOWriteB(Port
, Buffer
);
447 IOWriteStrB(Port
, Buffer
, DataCount
);
449 else if (DataSize
== sizeof(USHORT
))
452 IOWriteW(Port
, Buffer
);
454 IOWriteStrW(Port
, Buffer
, DataCount
);
456 else if (DataSize
== sizeof(ULONG
))
459 IOWriteD(Port
, Buffer
);
461 IOWriteStrD(Port
, Buffer
, DataCount
);
465 PBYTE Address
= (PBYTE
)Buffer
;
469 ULONG CurrentPort
= Port
;
471 UCHAR NewDataSize
= DataSize
;
474 Count
= NewDataSize
/ sizeof(ULONG
);
475 NewDataSize
= NewDataSize
% sizeof(ULONG
);
478 IOWriteD(CurrentPort
, (PULONG
)Address
);
479 CurrentPort
+= sizeof(ULONG
);
480 Address
+= sizeof(ULONG
);
484 Count
= NewDataSize
/ sizeof(USHORT
);
485 NewDataSize
= NewDataSize
% sizeof(USHORT
);
488 IOWriteW(CurrentPort
, (PUSHORT
)Address
);
489 CurrentPort
+= sizeof(USHORT
);
490 Address
+= sizeof(USHORT
);
494 Count
= NewDataSize
/ sizeof(UCHAR
);
495 NewDataSize
= NewDataSize
% sizeof(UCHAR
);
498 IOWriteB(CurrentPort
, (PUCHAR
)Address
);
499 CurrentPort
+= sizeof(UCHAR
);
500 Address
+= sizeof(UCHAR
);
504 ASSERT(NewDataSize
== 0);
513 VDDInstallIOHook(HANDLE hVdd
,
515 PVDD_IO_PORTRANGE pPortRange
,
516 PVDD_IO_HANDLERS IOhandler
)
518 /* Check possible validity of the VDD handle */
519 if (hVdd
== 0 || hVdd
== INVALID_HANDLE_VALUE
) return FALSE
;
521 /* Loop for each range of I/O ports */
526 /* Register the range of I/O ports */
527 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
530 * Don't do anything if the I/O port is already
531 * handled internally or externally.
533 if (IoPortProc
[i
].hVdd
!= 0)
535 DPRINT1("IoPortProc[0x%X] already registered\n", i
);
539 /* Register wrt. the VDD */
540 IoPortProc
[i
].hVdd
= hVdd
;
542 /* Disable the internal handlers */
543 IoPortProc
[i
].IoHandlers
.InB
= NULL
;
544 IoPortProc
[i
].IoHandlers
.InW
= NULL
;
545 IoPortProc
[i
].IoHandlers
.InD
= NULL
;
547 IoPortProc
[i
].IoHandlers
.InsB
= NULL
;
548 IoPortProc
[i
].IoHandlers
.InsW
= NULL
;
549 IoPortProc
[i
].IoHandlers
.InsD
= NULL
;
551 IoPortProc
[i
].IoHandlers
.OutB
= NULL
;
552 IoPortProc
[i
].IoHandlers
.OutW
= NULL
;
553 IoPortProc
[i
].IoHandlers
.OutD
= NULL
;
555 IoPortProc
[i
].IoHandlers
.OutsB
= NULL
;
556 IoPortProc
[i
].IoHandlers
.OutsW
= NULL
;
557 IoPortProc
[i
].IoHandlers
.OutsD
= NULL
;
559 /* Save our handlers */
560 IoPortProc
[i
].VddIoHandlers
= *IOhandler
;
563 /* Go to the next range */
573 VDDDeInstallIOHook(HANDLE hVdd
,
575 PVDD_IO_PORTRANGE pPortRange
)
577 /* Check possible validity of the VDD handle */
578 if (hVdd
== 0 || hVdd
== INVALID_HANDLE_VALUE
) return;
580 /* Loop for each range of I/O ports */
585 /* Unregister the range of I/O ports */
586 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
589 * Don't do anything if we don't own the I/O port.
591 if (IoPortProc
[i
].hVdd
!= hVdd
)
593 DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i
);
598 * Put automagically all the fields to zero:
599 * the hVdd gets unregistered as well as all the handlers.
601 // IoPortProc[i] = {NULL};
602 ZeroMemory(&IoPortProc
[i
], sizeof(IoPortProc
[i
]));
605 /* Go to the next range */