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
);
103 while (Count
--) *Buffer
++ = IOReadB(Port
);
111 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
112 IoPortProc
[Port
].IoHandlers
.OutB
)
114 IoPortProc
[Port
].IoHandlers
.OutB(Port
, Buffer
);
116 else if (IoPortProc
[Port
].hVdd
> 0 &&
117 IoPortProc
[Port
].VddIoHandlers
.outb_handler
)
119 ASSERT(Port
<= MAXWORD
);
120 IoPortProc
[Port
].VddIoHandlers
.outb_handler((WORD
)Port
, Buffer
);
125 DPRINT("Write to unknown port: 0x%X\n", Port
);
130 IOWriteStrB(ULONG Port
,
134 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
135 IoPortProc
[Port
].IoHandlers
.OutsB
)
137 IoPortProc
[Port
].IoHandlers
.OutsB(Port
, Buffer
, Count
);
139 else if (IoPortProc
[Port
].hVdd
> 0 &&
140 IoPortProc
[Port
].VddIoHandlers
.outsb_handler
)
142 ASSERT(Port
<= MAXWORD
);
143 ASSERT(Count
<= MAXWORD
);
144 IoPortProc
[Port
].VddIoHandlers
.outsb_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
148 while (Count
--) IOWriteB(Port
, *Buffer
++);
155 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
156 IoPortProc
[Port
].IoHandlers
.InW
)
158 return IoPortProc
[Port
].IoHandlers
.InW(Port
);
160 else if (IoPortProc
[Port
].hVdd
> 0 &&
161 IoPortProc
[Port
].VddIoHandlers
.inw_handler
)
164 ASSERT(Port
<= MAXWORD
);
165 IoPortProc
[Port
].VddIoHandlers
.inw_handler((WORD
)Port
, &Data
);
172 // FIXME: Is it ok on Little endian and Big endian ??
174 High
= IOReadB(Port
+ sizeof(UCHAR
));
175 return MAKEWORD(Low
, High
);
180 IOReadStrW(ULONG Port
,
184 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
185 IoPortProc
[Port
].IoHandlers
.InsW
)
187 IoPortProc
[Port
].IoHandlers
.InsW(Port
, Buffer
, Count
);
189 else if (IoPortProc
[Port
].hVdd
> 0 &&
190 IoPortProc
[Port
].VddIoHandlers
.insw_handler
)
192 ASSERT(Port
<= MAXWORD
);
193 ASSERT(Count
<= MAXWORD
);
194 IoPortProc
[Port
].VddIoHandlers
.insw_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
198 while (Count
--) *Buffer
++ = IOReadW(Port
);
206 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
207 IoPortProc
[Port
].IoHandlers
.OutW
)
209 IoPortProc
[Port
].IoHandlers
.OutW(Port
, Buffer
);
211 else if (IoPortProc
[Port
].hVdd
> 0 &&
212 IoPortProc
[Port
].VddIoHandlers
.outw_handler
)
214 ASSERT(Port
<= MAXWORD
);
215 IoPortProc
[Port
].VddIoHandlers
.outw_handler((WORD
)Port
, Buffer
);
219 // FIXME: Is it ok on Little endian and Big endian ??
220 IOWriteB(Port
, LOBYTE(Buffer
));
221 IOWriteB(Port
+ sizeof(UCHAR
), HIBYTE(Buffer
));
226 IOWriteStrW(ULONG Port
,
230 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
231 IoPortProc
[Port
].IoHandlers
.OutsW
)
233 IoPortProc
[Port
].IoHandlers
.OutsW(Port
, Buffer
, Count
);
235 else if (IoPortProc
[Port
].hVdd
> 0 &&
236 IoPortProc
[Port
].VddIoHandlers
.outsw_handler
)
238 ASSERT(Port
<= MAXWORD
);
239 ASSERT(Count
<= MAXWORD
);
240 IoPortProc
[Port
].VddIoHandlers
.outsw_handler((WORD
)Port
, Buffer
, (WORD
)Count
);
244 while (Count
--) IOWriteW(Port
, *Buffer
++);
251 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
252 IoPortProc
[Port
].IoHandlers
.InD
)
254 return IoPortProc
[Port
].IoHandlers
.InD(Port
);
260 // FIXME: Is it ok on Little endian and Big endian ??
262 High
= IOReadW(Port
+ sizeof(USHORT
));
263 return MAKELONG(Low
, High
);
268 IOReadStrD(ULONG Port
,
272 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
273 IoPortProc
[Port
].IoHandlers
.InsD
)
275 IoPortProc
[Port
].IoHandlers
.InsD(Port
, Buffer
, Count
);
279 while (Count
--) *Buffer
++ = IOReadD(Port
);
287 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
288 IoPortProc
[Port
].IoHandlers
.OutD
)
290 IoPortProc
[Port
].IoHandlers
.OutD(Port
, Buffer
);
294 // FIXME: Is it ok on Little endian and Big endian ??
295 IOWriteW(Port
, LOWORD(Buffer
));
296 IOWriteW(Port
+ sizeof(USHORT
), HIWORD(Buffer
));
301 IOWriteStrD(ULONG Port
,
305 if (IoPortProc
[Port
].hVdd
== INVALID_HANDLE_VALUE
&&
306 IoPortProc
[Port
].IoHandlers
.OutsD
)
308 IoPortProc
[Port
].IoHandlers
.OutsD(Port
, Buffer
, Count
);
312 while (Count
--) IOWriteD(Port
, *Buffer
++);
317 VOID
RegisterIoPort(ULONG Port
,
318 EMULATOR_INB_PROC InHandler
,
319 EMULATOR_OUTB_PROC OutHandler
)
321 if (IoPortProc
[Port
].IoHandlers
.InB
== NULL
)
322 IoPortProc
[Port
].IoHandlers
.InB
= InHandler
;
324 DPRINT1("IoPortProc[0x%X].IoHandlers.InB already registered\n", Port
);
326 if (IoPortProc
[Port
].IoHandlers
.OutB
== NULL
)
327 IoPortProc
[Port
].IoHandlers
.OutB
= OutHandler
;
329 DPRINT1("IoPortProc[0x%X].IoHandlers.OutB already registered\n", Port
);
331 /* We hold the I/O port internally */
332 IoPortProc
[Port
].hVdd
= INVALID_HANDLE_VALUE
;
335 VOID
UnregisterIoPort(ULONG Port
)
338 * Put automagically all the fields to zero:
339 * the hVdd gets unregistered as well as all the handlers.
341 // IoPortProc[Port] = {NULL};
342 RtlZeroMemory(&IoPortProc
[Port
], sizeof(IoPortProc
[Port
]));
346 EmulatorReadIo(PFAST486_STATE State
,
352 UNREFERENCED_PARAMETER(State
);
354 if (DataSize
== 0 || DataCount
== 0) return;
356 if (DataSize
== sizeof(UCHAR
))
359 *(PUCHAR
)Buffer
= IOReadB(Port
);
361 IOReadStrB(Port
, Buffer
, DataCount
);
363 else if (DataSize
== sizeof(USHORT
))
366 *(PUSHORT
)Buffer
= IOReadW(Port
);
368 IOReadStrW(Port
, Buffer
, DataCount
);
370 else if (DataSize
== sizeof(ULONG
))
373 *(PULONG
)Buffer
= IOReadD(Port
);
375 IOReadStrD(Port
, Buffer
, DataCount
);
379 PUCHAR Address
= (PUCHAR
)Buffer
;
383 ULONG CurrentPort
= Port
;
385 UCHAR NewDataSize
= DataSize
;
388 Count
= NewDataSize
>> 2; // NewDataSize / sizeof(ULONG);
389 NewDataSize
= NewDataSize
& 3; // NewDataSize % sizeof(ULONG);
392 *(PULONG
)Address
= IOReadD(CurrentPort
);
393 CurrentPort
+= sizeof(ULONG
);
394 Address
+= sizeof(ULONG
);
398 Count
= NewDataSize
>> 1; // NewDataSize / sizeof(USHORT);
399 NewDataSize
= NewDataSize
& 1; // NewDataSize % sizeof(USHORT);
402 *(PUSHORT
)Address
= IOReadW(CurrentPort
);
403 CurrentPort
+= sizeof(USHORT
);
404 Address
+= sizeof(USHORT
);
408 Count
= NewDataSize
; // NewDataSize / sizeof(UCHAR);
409 // NewDataSize = NewDataSize % sizeof(UCHAR);
412 *(PUCHAR
)Address
= IOReadB(CurrentPort
);
413 CurrentPort
+= sizeof(UCHAR
);
414 Address
+= sizeof(UCHAR
);
421 EmulatorWriteIo(PFAST486_STATE State
,
427 UNREFERENCED_PARAMETER(State
);
429 if (DataSize
== 0 || DataCount
== 0) return;
431 if (DataSize
== sizeof(UCHAR
))
434 IOWriteB(Port
, *(PUCHAR
)Buffer
);
436 IOWriteStrB(Port
, Buffer
, DataCount
);
438 else if (DataSize
== sizeof(USHORT
))
441 IOWriteW(Port
, *(PUSHORT
)Buffer
);
443 IOWriteStrW(Port
, Buffer
, DataCount
);
445 else if (DataSize
== sizeof(ULONG
))
448 IOWriteD(Port
, *(PULONG
)Buffer
);
450 IOWriteStrD(Port
, Buffer
, DataCount
);
454 PUCHAR Address
= (PUCHAR
)Buffer
;
458 ULONG CurrentPort
= Port
;
460 UCHAR NewDataSize
= DataSize
;
463 Count
= NewDataSize
>> 2; // NewDataSize / sizeof(ULONG);
464 NewDataSize
= NewDataSize
& 3; // NewDataSize % sizeof(ULONG);
467 IOWriteD(CurrentPort
, *(PULONG
)Address
);
468 CurrentPort
+= sizeof(ULONG
);
469 Address
+= sizeof(ULONG
);
473 Count
= NewDataSize
>> 1; // NewDataSize / sizeof(USHORT);
474 NewDataSize
= NewDataSize
& 1; // NewDataSize % sizeof(USHORT);
477 IOWriteW(CurrentPort
, *(PUSHORT
)Address
);
478 CurrentPort
+= sizeof(USHORT
);
479 Address
+= sizeof(USHORT
);
483 Count
= NewDataSize
; // NewDataSize / sizeof(UCHAR);
484 // NewDataSize = NewDataSize % sizeof(UCHAR);
487 IOWriteB(CurrentPort
, *(PUCHAR
)Address
);
488 CurrentPort
+= sizeof(UCHAR
);
489 Address
+= sizeof(UCHAR
);
499 VDDInstallIOHook(HANDLE hVdd
,
501 PVDD_IO_PORTRANGE pPortRange
,
502 PVDD_IO_HANDLERS IOhandler
)
504 /* Check possible validity of the VDD handle */
505 if (hVdd
== 0 || hVdd
== INVALID_HANDLE_VALUE
) return FALSE
;
507 /* Loop for each range of I/O ports */
512 /* Register the range of I/O ports */
513 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
516 * Don't do anything if the I/O port is already
517 * handled internally or externally.
519 if (IoPortProc
[i
].hVdd
!= 0)
521 DPRINT1("IoPortProc[0x%X] already registered\n", i
);
525 /* Register wrt. the VDD */
526 IoPortProc
[i
].hVdd
= hVdd
;
528 /* Disable the internal handlers */
529 IoPortProc
[i
].IoHandlers
.InB
= NULL
;
530 IoPortProc
[i
].IoHandlers
.InW
= NULL
;
531 IoPortProc
[i
].IoHandlers
.InD
= NULL
;
533 IoPortProc
[i
].IoHandlers
.InsB
= NULL
;
534 IoPortProc
[i
].IoHandlers
.InsW
= NULL
;
535 IoPortProc
[i
].IoHandlers
.InsD
= NULL
;
537 IoPortProc
[i
].IoHandlers
.OutB
= NULL
;
538 IoPortProc
[i
].IoHandlers
.OutW
= NULL
;
539 IoPortProc
[i
].IoHandlers
.OutD
= NULL
;
541 IoPortProc
[i
].IoHandlers
.OutsB
= NULL
;
542 IoPortProc
[i
].IoHandlers
.OutsW
= NULL
;
543 IoPortProc
[i
].IoHandlers
.OutsD
= NULL
;
545 /* Save our handlers */
546 IoPortProc
[i
].VddIoHandlers
= *IOhandler
;
549 /* Go to the next range */
559 VDDDeInstallIOHook(HANDLE hVdd
,
561 PVDD_IO_PORTRANGE pPortRange
)
563 /* Check possible validity of the VDD handle */
564 if (hVdd
== 0 || hVdd
== INVALID_HANDLE_VALUE
) return;
566 /* Loop for each range of I/O ports */
571 /* Unregister the range of I/O ports */
572 for (i
= pPortRange
->First
; i
<= pPortRange
->Last
; ++i
)
575 * Don't do anything if we don't own the I/O port.
577 if (IoPortProc
[i
].hVdd
!= hVdd
)
579 DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i
);
584 * Put automagically all the fields to zero:
585 * the hVdd gets unregistered as well as all the handlers.
587 // IoPortProc[i] = {NULL};
588 RtlZeroMemory(&IoPortProc
[i
], sizeof(IoPortProc
[i
]));
591 /* Go to the next range */