-
Notifications
You must be signed in to change notification settings - Fork 1
/
ps8042.hpp
214 lines (179 loc) · 5.77 KB
/
ps8042.hpp
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#pragma once
#include "cpuio.hpp"
namespace ps8042 {
namespace stdData {
using namespace cpuio;
namespace ioport {
constexpr port_t data = 0x60;
constexpr port_t status = 0x64;
constexpr port_t cmd = 0x64;
}
namespace statusBitMask {
constexpr uint8_t outFull = 1 << 0;
constexpr uint8_t inFull = 1 << 1;
constexpr uint8_t postOk = 1 << 2;
constexpr uint8_t dataForController = 1 << 3;
constexpr uint8_t timeout = 1 << 6;
constexpr uint8_t parityErr = 1 << 7;
}
namespace configBitMask {
constexpr uint8_t port1IRQ = 1 << 0;
constexpr uint8_t port2IRQ = 1 << 1;
constexpr uint8_t postOk = 1 << 2;
constexpr uint8_t port1Clock = 1 << 4;
constexpr uint8_t port2Clock = 1 << 5;
constexpr uint8_t port1Translate = 1 << 6;
}
namespace selfTest_response {
namespace controller {
constexpr uint8_t ok = 0x55;
constexpr uint8_t fail = 0xfc;
}
namespace port {
constexpr uint8_t ok = 0x00;
namespace clockStuck {
constexpr uint8_t low = 0x01;
constexpr uint8_t high = 0x02;
}
namespace dataStuck {
constexpr uint8_t low = 0x03;
constexpr uint8_t high = 0x04;
}
}
}
namespace cmd {
namespace controller {
constexpr uint8_t rbyte0 = 0x20;
constexpr uint8_t rcfg = rbyte0;
// constexpr uint8_t rbyten = rbyte0 + n; // non-std
constexpr uint8_t wbyte0 = 0x60;
constexpr uint8_t wcfg = wbyte0;
// constexpr uint8_t wbyten = wbyte0 + n; // non-std
constexpr uint8_t tst = 0xaa;
// constexpr uint8_t diag_dump = 0xac; // non-std
constexpr uint8_t mov_status4to7_bits0to3 = 0xc1;
constexpr uint8_t mov_status4to7_bits4to7 = 0xc2;
// constexpr uint8_t rin_port = 0xc0; // non-std
constexpr uint8_t rout_port = 0xd0;
constexpr uint8_t wout_port = 0xd1;
// constexpr uint8_t pulselow_line0 = 0xf0; // non-std
constexpr uint8_t pulselow_reset = 0xfe; // cpu reset
// constexpr uint8_t pulselow_linen = 0xf0; // non-std
}
namespace port1 {
constexpr uint8_t tst = 0xab;
constexpr uint8_t off = 0xad;
constexpr uint8_t on = 0xae;
constexpr uint8_t wout_port = 0xd2;
}
namespace port2 { // fixme: port 2 might be unavailable
constexpr uint8_t off = 0xa7;
constexpr uint8_t on = 0xa8;
constexpr uint8_t tst = 0xa9;
constexpr uint8_t win_port = 0xd4;
constexpr uint8_t wout_port = 0xd3;
}
}
}
struct ControllerStatus {
public:
constexpr ControllerStatus(uint8_t s) :
s_(s)
{}
constexpr bool outFull() {
return s_ & stdData::statusBitMask::outFull;
}
constexpr bool inFull() {
return s_ & stdData::statusBitMask::inFull;
}
constexpr bool postOk() {
return s_ & stdData::statusBitMask::postOk;
}
constexpr bool dataForController() {
return s_ & stdData::statusBitMask::dataForController;
}
constexpr bool timeout() {
return s_ & stdData::statusBitMask::timeout;
}
constexpr bool parityErr() {
return s_ & stdData::statusBitMask::parityErr;
}
constexpr bool raw() {
return s_;
}
private:
uint8_t s_;
};
struct ControllerConfig {
public:
constexpr ControllerConfig(uint8_t s) :
s_(s)
{}
constexpr bool port1IRQ() {
return s_ & stdData::configBitMask::port1IRQ;
}
constexpr ControllerConfig port1IRQ(bool v) {
return set(stdData::configBitMask::port1IRQ, v);
}
constexpr bool port2IRQ() {
return s_ & stdData::configBitMask::port2IRQ;
}
constexpr ControllerConfig port2IRQ(bool v) {
return set(stdData::configBitMask::port2IRQ, v);
}
constexpr bool postOk() {
return s_ & stdData::configBitMask::postOk;
}
constexpr ControllerConfig postOk(bool v) {
return set(stdData::configBitMask::postOk, v);
}
constexpr bool port1Clock() {
return !(s_ & stdData::configBitMask::port1Clock);
}
constexpr ControllerConfig port1Clock(bool v) {
return set(stdData::configBitMask::port1Clock, !v);
}
constexpr bool port2Clock() {
return !(s_ & stdData::configBitMask::port2Clock);
}
constexpr ControllerConfig port2Clock(bool v) {
return set(stdData::configBitMask::port2Clock, !v);
}
constexpr bool port1Translate() {
return s_ & stdData::configBitMask::port1Translate;
}
constexpr ControllerConfig port1Translate(bool v) {
return set(stdData::configBitMask::port1Translate, v);
}
constexpr bool raw() {
return s_;
}
private:
uint8_t s_;
constexpr ControllerConfig set(uint8_t mask, bool v) {
if (v)
return ControllerConfig(s_ & mask);
else
return ControllerConfig(s_ & ~mask);
}
};
// fixme: init USB first if you are going to do that at all
class Controller { // fixme: some ancient apple hardware doesnt have a 8042
public:
Controller();
~Controller();
Controller(const Controller& that) = delete;
Controller(Controller&& that) = default;
Controller& operator=(const Controller& that) = delete;
Controller& operator=(Controller&& that) = default;
ControllerStatus status() const;
ControllerConfig config() const;
void config(ControllerConfig cfg) const;
void cmd(uint8_t cmd) const;
uint8_t read() const;
void write(uint8_t v) const;
uint8_t poll() const;
void blockW(uint8_t v) const;
private:
};
}