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 *******************************************************************/
18 /* PRIVATE VARIABLES **********************************************************/
20 typedef struct _EMULATOR_IO_HANDLERS
22 EMULATOR_INB_PROC InB
;
23 EMULATOR_INW_PROC InW
;
24 EMULATOR_IND_PROC InD
;
26 EMULATOR_INSB_PROC InsB
;
27 EMULATOR_INSW_PROC InsW
;
28 EMULATOR_INSD_PROC InsD
;
30 EMULATOR_OUTB_PROC OutB
;
31 EMULATOR_OUTW_PROC OutW
;
32 EMULATOR_OUTD_PROC OutD
;
34 EMULATOR_OUTSB_PROC OutsB
;
35 EMULATOR_OUTSW_PROC OutsW
;
36 EMULATOR_OUTSD_PROC OutsD
;
37 } EMULATOR_IO_HANDLERS
, *PEMULATOR_IO_HANDLERS
;
39 typedef struct _EMULATOR_IOPORT_HANDLERS
41 HANDLE hVdd
; // == NULL if unused,
42 // INVALID_HANDLE_VALUE if handled internally,
43 // a valid VDD handle if handled externally.
46 /* For Windows compatibility only, not used internally... */
47 VDD_IO_HANDLERS VddIoHandlers
;
49 /* ... we use these members internally */
50 EMULATOR_IO_HANDLERS IoHandlers
;
52 } EMULATOR_IOPORT_HANDLERS
, *PEMULATOR_IOPORT_HANDLERS
;
55 * This is the list of registered I/O Port handlers.
57 EMULATOR_IOPORT_HANDLERS IoPortProc
[EMULATOR_MAX_IOPORTS_NUM
] = {{NULL
}};
59 /* PUBLIC FUNCTIONS ***********************************************************/
64 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
65 IoPortProc
[Port
].IoHandlers
.InB
)
67 return IoPortProc
[Port
].IoHandlers
.InB(Port
);
69 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
70 IoPortProc
[Port
].VddIoHandlers
.inb_handler
)
73 ASSERT(Port
<= MAXWORD
);
74 IoPortProc
[Port
].VddIoHandlers
.inb_handler(Port
, &Data
);
79 /* Return an empty port byte value */
80 DPRINT("Read from unknown port: 0x%X\n", Port
);
86 IOReadStrB(USHORT Port
,
90 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
91 IoPortProc
[Port
].IoHandlers
.InsB
)
93 IoPortProc
[Port
].IoHandlers
.InsB(Port
, Buffer
, Count
);
95 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
96 IoPortProc
[Port
].VddIoHandlers
.insb_handler
)
98 ASSERT(Port
<= MAXWORD
);
99 ASSERT(Count
<= MAXWORD
);
100 IoPortProc
[Port
].VddIoHandlers
.insb_handler(Port
, Buffer
, (WORD
)Count
);
104 while (Count
--) *Buffer
++ = IOReadB(Port
);
109 IOWriteB(USHORT Port
,
112 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
113 IoPortProc
[Port
].IoHandlers
.OutB
)
115 IoPortProc
[Port
].IoHandlers
.OutB(Port
, Buffer
);
117 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
118 IoPortProc
[Port
].VddIoHandlers
.outb_handler
)
120 ASSERT(Port
<= MAXWORD
);
121 IoPortProc
[Port
].VddIoHandlers
.outb_handler(Port
, Buffer
);
126 DPRINT("Write to unknown port: 0x%X\n", Port
);
131 IOWriteStrB(USHORT Port
,
135 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
136 IoPortProc
[Port
].IoHandlers
.OutsB
)
138 IoPortProc
[Port
].IoHandlers
.OutsB(Port
, Buffer
, Count
);
140 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
141 IoPortProc
[Port
].VddIoHandlers
.outsb_handler
)
143 ASSERT(Port
<= MAXWORD
);
144 ASSERT(Count
<= MAXWORD
);
145 IoPortProc
[Port
].VddIoHandlers
.outsb_handler(Port
, Buffer
, (WORD
)Count
);
149 while (Count
--) IOWriteB(Port
, *Buffer
++);
156 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
157 IoPortProc
[Port
].IoHandlers
.InW
)
159 return IoPortProc
[Port
].IoHandlers
.InW(Port
);
161 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
162 IoPortProc
[Port
].VddIoHandlers
.inw_handler
)
165 ASSERT(Port
<= MAXWORD
);
166 IoPortProc
[Port
].VddIoHandlers
.inw_handler(Port
, &Data
);
173 // FIXME: Is it ok on Little endian and Big endian ??
175 High
= IOReadB(Port
+ sizeof(UCHAR
));
176 return MAKEWORD(Low
, High
);
181 IOReadStrW(USHORT Port
,
185 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
186 IoPortProc
[Port
].IoHandlers
.InsW
)
188 IoPortProc
[Port
].IoHandlers
.InsW(Port
, Buffer
, Count
);
190 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
191 IoPortProc
[Port
].VddIoHandlers
.insw_handler
)
193 ASSERT(Port
<= MAXWORD
);
194 ASSERT(Count
<= MAXWORD
);
195 IoPortProc
[Port
].VddIoHandlers
.insw_handler(Port
, Buffer
, (WORD
)Count
);
199 while (Count
--) *Buffer
++ = IOReadW(Port
);
204 IOWriteW(USHORT Port
,
207 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
208 IoPortProc
[Port
].IoHandlers
.OutW
)
210 IoPortProc
[Port
].IoHandlers
.OutW(Port
, Buffer
);
212 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
213 IoPortProc
[Port
].VddIoHandlers
.outw_handler
)
215 ASSERT(Port
<= MAXWORD
);
216 IoPortProc
[Port
].VddIoHandlers
.outw_handler(Port
, Buffer
);
220 // FIXME: Is it ok on Little endian and Big endian ??
221 IOWriteB(Port
, LOBYTE(Buffer
));
222 IOWriteB(Port
+ sizeof(UCHAR
), HIBYTE(Buffer
));
227 IOWriteStrW(USHORT Port
,
231 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
232 IoPortProc
[Port
].IoHandlers
.OutsW
)
234 IoPortProc
[Port
].IoHandlers
.OutsW(Port
, Buffer
, Count
);
236 else if (IoPortProc
[Port
].hVdd
!= NULL
&& IoPortProc
[Port
].hVdd
!= INVALID_HANDLE_VALUE
&&
237 IoPortProc
[Port
].VddIoHandlers
.outsw_handler
)
239 ASSERT(Port
<= MAXWORD
);
240 ASSERT(Count
<= MAXWORD
);
241 IoPortProc
[Port
].VddIoHandlers
.outsw_handler(Port
, Buffer
, (WORD
)Count
);
245 while (Count
--) IOWriteW(Port
, *Buffer
++);
252 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
253 IoPortProc
[Port
].IoHandlers
.InD
)
255 return IoPortProc
[Port
].IoHandlers
.InD(Port
);
261 // FIXME: Is it ok on Little endian and Big endian ??
263 High
= IOReadW(Port
+ sizeof(USHORT
));
264 return MAKELONG(Low
, High
);
269 IOReadStrD(USHORT Port
,
273 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
274 IoPortProc
[Port
].IoHandlers
.InsD
)
276 IoPortProc
[Port
].IoHandlers
.InsD(Port
, Buffer
, Count
);
280 while (Count
--) *Buffer
++ = IOReadD(Port
);
285 IOWriteD(USHORT Port
,
288 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
289 IoPortProc
[Port
].IoHandlers
.OutD
)
291 IoPortProc
[Port
].IoHandlers
.OutD(Port
, Buffer
);
295 // FIXME: Is it ok on Little endian and Big endian ??
296 IOWriteW(Port
, LOWORD(Buffer
));
297 IOWriteW(Port
+ sizeof(USHORT
), HIWORD(Buffer
));
302 IOWriteStrD(USHORT Port
,
306 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
307 IoPortProc
[Port
].IoHandlers
.OutsD
)
309 IoPortProc
[Port
].IoHandlers
.OutsD(Port
, Buffer
, Count
);
313 while (Count
--) IOWriteD(Port
, *Buffer
++);
318 VOID
RegisterIoPort(USHORT Port
,
319 EMULATOR_INB_PROC InHandler
,
320 EMULATOR_OUTB_PROC OutHandler
)
322 if (IoPortProc
[Port
].IoHandlers
.InB
== NULL
)
323 IoPortProc
[Port
].IoHandlers
.InB
= InHandler
;
325 DPRINT1("IoPortProc[0x%X].IoHandlers.InB already registered\n", Port
);
327 if (IoPortProc
[Port
].IoHandlers
.OutB
== NULL
)
328 IoPortProc
[Port
].IoHandlers
.OutB
= OutHandler
;
330 DPRINT1("IoPortProc[0x%X].IoHandlers.OutB already registered\n", Port
);
332 /* We hold the I/O port internally */
333 IoPortProc
[Port
].hVdd
= INVALID_HANDLE_VALUE
;
336 VOID
UnregisterIoPort(USHORT Port
)
339 * Put automagically all the fields to zero:
340 * the hVdd gets unregistered as well as all the handlers.
342 // IoPortProc[Port] = {NULL};
343 RtlZeroMemory(&IoPortProc
[Port
], sizeof(IoPortProc
[Port
]));
347 EmulatorReadIo(PFAST486_STATE State
,
353 UNREFERENCED_PARAMETER(State
);
355 if (DataSize
== 0 || DataCount
== 0) return;
357 if (DataSize
== sizeof(UCHAR
))
360 *(PUCHAR
)Buffer
= IOReadB(Port
);
362 IOReadStrB(Port
, Buffer
, DataCount
);
364 else if (DataSize
== sizeof(USHORT
))
367 *(PUSHORT
)Buffer
= IOReadW(Port
);
369 IOReadStrW(Port
, Buffer
, DataCount
);
371 else if (DataSize
== sizeof(ULONG
))
374 *(PULONG
)Buffer
= IOReadD(Port
);
376 IOReadStrD(Port
, Buffer
, DataCount
);
380 PUCHAR Address
= (PUCHAR
)Buffer
;
384 ULONG CurrentPort
= Port
;
386 UCHAR NewDataSize
= DataSize
;
389 Count
= NewDataSize
>> 2; // NewDataSize / sizeof(ULONG);
390 NewDataSize
= NewDataSize
& 3; // NewDataSize % sizeof(ULONG);
393 *(PULONG
)Address
= IOReadD(CurrentPort
);
394 CurrentPort
+= sizeof(ULONG
);
395 Address
+= sizeof(ULONG
);
399 Count
= NewDataSize
>> 1; // NewDataSize / sizeof(USHORT);
400 NewDataSize
= NewDataSize
& 1; // NewDataSize % sizeof(USHORT);
403 *(PUSHORT
)Address
= IOReadW(CurrentPort
);
404 CurrentPort
+= sizeof(USHORT
);
405 Address
+= sizeof(USHORT
);
409 Count
= NewDataSize
; // NewDataSize / sizeof(UCHAR);
410 // NewDataSize = NewDataSize % sizeof(UCHAR);
413 *(PUCHAR
)Address
= IOReadB(CurrentPort
);
414 CurrentPort
+= sizeof(UCHAR
);
415 Address
+= sizeof(UCHAR
);
422 EmulatorWriteIo(PFAST486_STATE State
,
428 UNREFERENCED_PARAMETER(State
);
430 if (DataSize
== 0 || DataCount
== 0) return;
432 if (DataSize
== sizeof(UCHAR
))
435 IOWriteB(Port
, *(PUCHAR
)Buffer
);
437 IOWriteStrB(Port
, Buffer
, DataCount
);
439 else if (DataSize
== sizeof(USHORT
))
442 IOWriteW(Port
, *(PUSHORT
)Buffer
);
444 IOWriteStrW(Port
, Buffer
, DataCount
);
446 else if (DataSize
== sizeof(ULONG
))
449 IOWriteD(Port
, *(PULONG
)Buffer
);
451 IOWriteStrD(Port
, Buffer
, DataCount
);
455 PUCHAR Address
= (PUCHAR
)Buffer
;
459 ULONG CurrentPort
= Port
;
461 UCHAR NewDataSize
= DataSize
;
464 Count
= NewDataSize
>> 2; // NewDataSize / sizeof(ULONG);
465 NewDataSize
= NewDataSize
& 3; // NewDataSize % sizeof(ULONG);
468 IOWriteD(CurrentPort
, *(PULONG
)Address
);
469 CurrentPort
+= sizeof(ULONG
);
470 Address
+= sizeof(ULONG
);
474 Count
= NewDataSize
>> 1; // NewDataSize / sizeof(USHORT);
475 NewDataSize
= NewDataSize
& 1; // NewDataSize % sizeof(USHORT);
478 IOWriteW(CurrentPort
, *(PUSHORT
)Address
);
479 CurrentPort
+= sizeof(USHORT
);
480 Address
+= sizeof(USHORT
);
484 Count
= NewDataSize
; // NewDataSize / sizeof(UCHAR);
485 // NewDataSize = NewDataSize % sizeof(UCHAR);
488 IOWriteB(CurrentPort
, *(PUCHAR
)Address
);
489 CurrentPort
+= sizeof(UCHAR
);
490 Address
+= sizeof(UCHAR
);
500 VDDInstallIOHook(IN HANDLE hVdd
,
502 IN PVDD_IO_PORTRANGE pPortRange
,
503 IN PVDD_IO_HANDLERS IoHandlers
)
507 /* Check validity of the VDD handle */
508 if (hVdd
== NULL
|| hVdd
== INVALID_HANDLE_VALUE
)
510 SetLastError(ERROR_INVALID_PARAMETER
);
514 /* Loop for each range of I/O ports */
517 /* Register the range of I/O ports */
518 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
521 * Don't do anything if the I/O port is already
522 * handled internally or externally.
524 if (IoPortProc
[i
].hVdd
!= NULL
)
526 DPRINT1("IoPortProc[0x%X] already registered\n", i
);
530 /* Register wrt. the VDD */
531 IoPortProc
[i
].hVdd
= hVdd
;
533 /* Disable the internal handlers */
534 IoPortProc
[i
].IoHandlers
.InB
= NULL
;
535 IoPortProc
[i
].IoHandlers
.InW
= NULL
;
536 IoPortProc
[i
].IoHandlers
.InD
= NULL
;
538 IoPortProc
[i
].IoHandlers
.InsB
= NULL
;
539 IoPortProc
[i
].IoHandlers
.InsW
= NULL
;
540 IoPortProc
[i
].IoHandlers
.InsD
= NULL
;
542 IoPortProc
[i
].IoHandlers
.OutB
= NULL
;
543 IoPortProc
[i
].IoHandlers
.OutW
= NULL
;
544 IoPortProc
[i
].IoHandlers
.OutD
= NULL
;
546 IoPortProc
[i
].IoHandlers
.OutsB
= NULL
;
547 IoPortProc
[i
].IoHandlers
.OutsW
= NULL
;
548 IoPortProc
[i
].IoHandlers
.OutsD
= NULL
;
550 /* Save our handlers */
551 IoPortProc
[i
].VddIoHandlers
= *IoHandlers
;
554 /* Go to the next range */
563 VDDDeInstallIOHook(IN HANDLE hVdd
,
565 IN PVDD_IO_PORTRANGE pPortRange
)
569 /* Check validity of the VDD handle */
570 if (hVdd
== NULL
|| hVdd
== INVALID_HANDLE_VALUE
)
572 SetLastError(ERROR_INVALID_PARAMETER
);
576 /* Loop for each range of I/O ports */
579 /* Unregister the range of I/O ports */
580 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
583 * Don't do anything if we don't own the I/O port.
585 if (IoPortProc
[i
].hVdd
!= hVdd
)
587 DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i
);
592 * Put automagically all the fields to zero:
593 * the hVdd gets unregistered as well as all the handlers.
595 // IoPortProc[i] = {NULL};
596 RtlZeroMemory(&IoPortProc
[i
], sizeof(IoPortProc
[i
]));
599 /* Go to the next range */