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 /* PUBLIC FUNCTIONS ***********************************************************/
63 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
64 IoPortProc
[Port
].IoHandlers
.InB
)
66 return IoPortProc
[Port
].IoHandlers
.InB(Port
);
68 else if (IoPortProc
[Port
].hVdd
> 0 &&
69 IoPortProc
[Port
].VddIoHandlers
.inb_handler
)
72 ASSERT(Port
<= MAXWORD
);
73 IoPortProc
[Port
].VddIoHandlers
.inb_handler((WORD
)Port
, &Data
);
78 /* Return an empty port byte value */
79 DPRINT("Read from unknown port: 0x%X\n", Port
);
85 IOReadStrB(ULONG Port
,
89 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
90 IoPortProc
[Port
].IoHandlers
.InsB
)
92 IoPortProc
[Port
].IoHandlers
.InsB(Port
, Buffer
, Count
);
94 else if (IoPortProc
[Port
].hVdd
> 0 &&
95 IoPortProc
[Port
].VddIoHandlers
.insb_handler
)
97 ASSERT(Port
<= MAXWORD
);
98 ASSERT(Count
<= MAXWORD
);
99 IoPortProc
[Port
].VddIoHandlers
.insb_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
104 *Buffer
++ = IOReadB(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
> 0 &&
118 IoPortProc
[Port
].VddIoHandlers
.outb_handler
)
120 ASSERT(Port
<= MAXWORD
);
121 IoPortProc
[Port
].VddIoHandlers
.outb_handler((WORD
)Port
, Buffer
);
126 DPRINT("Write to unknown port: 0x%X\n", Port
);
131 IOWriteStrB(ULONG 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
> 0 &&
141 IoPortProc
[Port
].VddIoHandlers
.outsb_handler
)
143 ASSERT(Port
<= MAXWORD
);
144 ASSERT(Count
<= MAXWORD
);
145 IoPortProc
[Port
].VddIoHandlers
.outsb_handler((WORD
)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
> 0 &&
162 IoPortProc
[Port
].VddIoHandlers
.inw_handler
)
165 ASSERT(Port
<= MAXWORD
);
166 IoPortProc
[Port
].VddIoHandlers
.inw_handler((WORD
)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(ULONG 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
> 0 &&
191 IoPortProc
[Port
].VddIoHandlers
.insw_handler
)
193 ASSERT(Port
<= MAXWORD
);
194 ASSERT(Count
<= MAXWORD
);
195 IoPortProc
[Port
].VddIoHandlers
.insw_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
200 *Buffer
++ = IOReadW(Port
);
208 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
209 IoPortProc
[Port
].IoHandlers
.OutW
)
211 IoPortProc
[Port
].IoHandlers
.OutW(Port
, Buffer
);
213 else if (IoPortProc
[Port
].hVdd
> 0 &&
214 IoPortProc
[Port
].VddIoHandlers
.outw_handler
)
216 ASSERT(Port
<= MAXWORD
);
217 IoPortProc
[Port
].VddIoHandlers
.outw_handler((WORD
)Port
, Buffer
);
221 // FIXME: Is it ok on Little endian and Big endian ??
222 IOWriteB(Port
, LOBYTE(Buffer
));
223 IOWriteB(Port
+ sizeof(UCHAR
), HIBYTE(Buffer
));
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
++);
253 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
254 IoPortProc
[Port
].IoHandlers
.InD
)
256 return IoPortProc
[Port
].IoHandlers
.InD(Port
);
262 // FIXME: Is it ok on Little endian and Big endian ??
264 High
= IOReadW(Port
+ sizeof(USHORT
));
265 return MAKELONG(Low
, High
);
270 IOReadStrD(ULONG Port
,
274 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
275 IoPortProc
[Port
].IoHandlers
.InsD
)
277 IoPortProc
[Port
].IoHandlers
.InsD(Port
, Buffer
, Count
);
282 *Buffer
++ = IOReadD(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(ULONG 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(ULONG 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(ULONG 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 ZeroMemory(&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 PBYTE Address
= (PBYTE
)Buffer
;
386 ULONG CurrentPort
= Port
;
388 UCHAR NewDataSize
= DataSize
;
391 Count
= NewDataSize
/ sizeof(ULONG
);
392 NewDataSize
= NewDataSize
% sizeof(ULONG
);
395 *(PULONG
)Address
= IOReadD(CurrentPort
);
396 CurrentPort
+= sizeof(ULONG
);
397 Address
+= sizeof(ULONG
);
401 Count
= NewDataSize
/ sizeof(USHORT
);
402 NewDataSize
= NewDataSize
% sizeof(USHORT
);
405 *(PUSHORT
)Address
= IOReadW(CurrentPort
);
406 CurrentPort
+= sizeof(USHORT
);
407 Address
+= sizeof(USHORT
);
411 Count
= NewDataSize
/ sizeof(UCHAR
);
412 NewDataSize
= NewDataSize
% sizeof(UCHAR
);
415 *(PUCHAR
)Address
= IOReadB(CurrentPort
);
416 CurrentPort
+= sizeof(UCHAR
);
417 Address
+= sizeof(UCHAR
);
421 ASSERT(NewDataSize
== 0);
427 EmulatorWriteIo(PFAST486_STATE State
,
433 UNREFERENCED_PARAMETER(State
);
435 if (DataSize
== 0 || DataCount
== 0) return;
437 if (DataSize
== sizeof(UCHAR
))
440 IOWriteB(Port
, *(PUCHAR
)Buffer
);
442 IOWriteStrB(Port
, Buffer
, DataCount
);
444 else if (DataSize
== sizeof(USHORT
))
447 IOWriteW(Port
, *(PUSHORT
)Buffer
);
449 IOWriteStrW(Port
, Buffer
, DataCount
);
451 else if (DataSize
== sizeof(ULONG
))
454 IOWriteD(Port
, *(PULONG
)Buffer
);
456 IOWriteStrD(Port
, Buffer
, DataCount
);
460 PBYTE Address
= (PBYTE
)Buffer
;
464 ULONG CurrentPort
= Port
;
466 UCHAR NewDataSize
= DataSize
;
469 Count
= NewDataSize
/ sizeof(ULONG
);
470 NewDataSize
= NewDataSize
% sizeof(ULONG
);
473 IOWriteD(CurrentPort
, *(PULONG
)Address
);
474 CurrentPort
+= sizeof(ULONG
);
475 Address
+= sizeof(ULONG
);
479 Count
= NewDataSize
/ sizeof(USHORT
);
480 NewDataSize
= NewDataSize
% sizeof(USHORT
);
483 IOWriteW(CurrentPort
, *(PUSHORT
)Address
);
484 CurrentPort
+= sizeof(USHORT
);
485 Address
+= sizeof(USHORT
);
489 Count
= NewDataSize
/ sizeof(UCHAR
);
490 NewDataSize
= NewDataSize
% sizeof(UCHAR
);
493 IOWriteB(CurrentPort
, *(PUCHAR
)Address
);
494 CurrentPort
+= sizeof(UCHAR
);
495 Address
+= sizeof(UCHAR
);
499 ASSERT(NewDataSize
== 0);
508 VDDInstallIOHook(HANDLE hVdd
,
510 PVDD_IO_PORTRANGE pPortRange
,
511 PVDD_IO_HANDLERS IOhandler
)
513 /* Check possible validity of the VDD handle */
514 if (hVdd
== 0 || hVdd
== INVALID_HANDLE_VALUE
) return FALSE
;
516 /* Loop for each range of I/O ports */
521 /* Register the range of I/O ports */
522 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
525 * Don't do anything if the I/O port is already
526 * handled internally or externally.
528 if (IoPortProc
[i
].hVdd
!= 0)
530 DPRINT1("IoPortProc[0x%X] already registered\n", i
);
534 /* Register wrt. the VDD */
535 IoPortProc
[i
].hVdd
= hVdd
;
537 /* Disable the internal handlers */
538 IoPortProc
[i
].IoHandlers
.InB
= NULL
;
539 IoPortProc
[i
].IoHandlers
.InW
= NULL
;
540 IoPortProc
[i
].IoHandlers
.InD
= NULL
;
542 IoPortProc
[i
].IoHandlers
.InsB
= NULL
;
543 IoPortProc
[i
].IoHandlers
.InsW
= NULL
;
544 IoPortProc
[i
].IoHandlers
.InsD
= NULL
;
546 IoPortProc
[i
].IoHandlers
.OutB
= NULL
;
547 IoPortProc
[i
].IoHandlers
.OutW
= NULL
;
548 IoPortProc
[i
].IoHandlers
.OutD
= NULL
;
550 IoPortProc
[i
].IoHandlers
.OutsB
= NULL
;
551 IoPortProc
[i
].IoHandlers
.OutsW
= NULL
;
552 IoPortProc
[i
].IoHandlers
.OutsD
= NULL
;
554 /* Save our handlers */
555 IoPortProc
[i
].VddIoHandlers
= *IOhandler
;
558 /* Go to the next range */
568 VDDDeInstallIOHook(HANDLE hVdd
,
570 PVDD_IO_PORTRANGE pPortRange
)
572 /* Check possible validity of the VDD handle */
573 if (hVdd
== 0 || hVdd
== INVALID_HANDLE_VALUE
) return;
575 /* Loop for each range of I/O ports */
580 /* Unregister the range of I/O ports */
581 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
584 * Don't do anything if we don't own the I/O port.
586 if (IoPortProc
[i
].hVdd
!= hVdd
)
588 DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i
);
593 * Put automagically all the fields to zero:
594 * the hVdd gets unregistered as well as all the handlers.
596 // IoPortProc[i] = {NULL};
597 ZeroMemory(&IoPortProc
[i
], sizeof(IoPortProc
[i
]));
600 /* Go to the next range */