1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Copyright (C) 2020-2021 The DOSBox Staging Team
* Copyright (C) 2002-2021 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_INOUT_H
#define DOSBOX_INOUT_H
#include "dosbox.h"
#include <functional>
using io_port_t = uint16_t; // DOS only supports 16-bit port addresses
using io_val_t = uint32_t; // Handling exists up to a dword (or less)
void IO_WriteB(io_port_t port, uint8_t val);
void IO_WriteW(io_port_t port, uint16_t val);
void IO_WriteD(io_port_t port, uint32_t val);
uint8_t IO_ReadB(io_port_t port);
uint16_t IO_ReadW(io_port_t port);
uint32_t IO_ReadD(io_port_t port);
// type-sized IO handler API
enum class io_width_t : uint8_t {
byte = 1, // bytes
word = 2, // bytes
dword = 4, // bytes
};
// Sanity check the IO sizes
static_assert(static_cast<size_t>(io_width_t::byte) == sizeof(uint8_t), "io_width_t::byte must be 1 byte");
static_assert(static_cast<size_t>(io_width_t::word) == sizeof(uint16_t), "io_width_t::word must be 2 bytes");
static_assert(static_cast<size_t>(io_width_t::dword) == sizeof(uint32_t), "io_width_t::dword must be 4 bytes");
constexpr int io_widths = 3; // byte, word, and dword
using io_read_f = std::function<io_val_t(io_port_t port, io_width_t width)>;
using io_write_f = std::function<void(io_port_t port, io_val_t val, io_width_t width)>;
void IO_RegisterReadHandler(io_port_t port,
io_read_f handler,
io_width_t max_width,
io_port_t range = 1);
void IO_RegisterWriteHandler(io_port_t port,
io_write_f handler,
io_width_t max_width,
io_port_t range = 1);
void IO_FreeReadHandler(io_port_t port,
io_width_t max_width,
io_port_t range = 1);
void IO_FreeWriteHandler(io_port_t port,
io_width_t max_width,
io_port_t range = 1);
/* Classes to manage the IO objects created by the various devices.
* The io objects will remove itself on destruction.*/
class IO_Base{
protected:
bool installed = false;
io_port_t m_port = 0u;
io_width_t m_width = io_width_t::byte;
io_port_t m_range = 0u;
};
class IO_ReadHandleObject: private IO_Base{
public:
void Install(io_port_t port,
io_read_f handler,
io_width_t max_width,
io_port_t range = 1);
void Uninstall();
~IO_ReadHandleObject();
};
class IO_WriteHandleObject: private IO_Base{
public:
void Install(io_port_t port,
io_write_f handler,
io_width_t max_width,
io_port_t range = 1);
void Uninstall();
~IO_WriteHandleObject();
};
static inline void IO_Write(io_port_t port, uint8_t val)
{
IO_WriteB(port,val);
}
static inline uint8_t IO_Read(io_port_t port)
{
// cast to be dropped after deprecating the Bitu IO handler API
return IO_ReadB(port);
}
#endif
|