kmi.cc (12645:65086402bfcb) kmi.cc (12659:3b44e9f66aac)
1/*
1/*
2 * Copyright (c) 2010, 2017 ARM Limited
2 * Copyright (c) 2010, 2017-2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 32 unchanged lines hidden (view full) ---

43
44#include "dev/arm/kmi.hh"
45
46#include "base/trace.hh"
47#include "base/vnc/vncinput.hh"
48#include "debug/Pl050.hh"
49#include "dev/arm/amba_device.hh"
50#include "dev/ps2.hh"
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 32 unchanged lines hidden (view full) ---

43
44#include "dev/arm/kmi.hh"
45
46#include "base/trace.hh"
47#include "base/vnc/vncinput.hh"
48#include "debug/Pl050.hh"
49#include "dev/arm/amba_device.hh"
50#include "dev/ps2.hh"
51#include "dev/ps2/device.hh"
51#include "mem/packet.hh"
52#include "mem/packet_access.hh"
53
52#include "mem/packet.hh"
53#include "mem/packet_access.hh"
54
54Pl050::Pl050(const Params *p)
55Pl050::Pl050(const Pl050Params *p)
55 : AmbaIntDevice(p, 0xfff), control(0), status(0x43), clkdiv(0),
56 : AmbaIntDevice(p, 0xfff), control(0), status(0x43), clkdiv(0),
56 rawInterrupts(0), ackNext(false), shiftDown(false),
57 vnc(p->vnc), driverInitialized(false),
58 intEvent([this]{ generateInterrupt(); }, name())
57 rawInterrupts(0),
58 intEvent([this]{ generateInterrupt(); }, name()),
59 ps2(p->ps2)
59{
60{
60 if (vnc) {
61 if (!p->is_mouse)
62 vnc->setKeyboard(this);
63 else
64 vnc->setMouse(this);
65 }
61 ps2->hostRegDataAvailable([this]() { this->updateIntStatus(); });
66}
67
68Tick
69Pl050::read(PacketPtr pkt)
70{
71 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
72
73 Addr daddr = pkt->getAddr() - pioAddr;
74
75 uint32_t data = 0;
76
77 switch (daddr) {
78 case kmiCr:
79 DPRINTF(Pl050, "Read Commmand: %#x\n", (uint32_t)control);
80 data = control;
81 break;
62}
63
64Tick
65Pl050::read(PacketPtr pkt)
66{
67 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
68
69 Addr daddr = pkt->getAddr() - pioAddr;
70
71 uint32_t data = 0;
72
73 switch (daddr) {
74 case kmiCr:
75 DPRINTF(Pl050, "Read Commmand: %#x\n", (uint32_t)control);
76 data = control;
77 break;
82 case kmiStat:
83 if (rxQueue.empty())
84 status.rxfull = 0;
85 else
86 status.rxfull = 1;
87
78
79 case kmiStat:
80 status.rxfull = ps2->hostDataAvailable() ? 1 : 0;
88 DPRINTF(Pl050, "Read Status: %#x\n", (uint32_t)status);
89 data = status;
90 break;
81 DPRINTF(Pl050, "Read Status: %#x\n", (uint32_t)status);
82 data = status;
83 break;
84
91 case kmiData:
85 case kmiData:
92 if (rxQueue.empty()) {
93 data = 0;
94 } else {
95 data = rxQueue.front();
96 rxQueue.pop_front();
97 }
86 data = ps2->hostDataAvailable() ? ps2->hostRead() : 0;
98 DPRINTF(Pl050, "Read Data: %#x\n", (uint32_t)data);
99 updateIntStatus();
100 break;
87 DPRINTF(Pl050, "Read Data: %#x\n", (uint32_t)data);
88 updateIntStatus();
89 break;
90
101 case kmiClkDiv:
102 data = clkdiv;
103 break;
91 case kmiClkDiv:
92 data = clkdiv;
93 break;
94
104 case kmiISR:
105 data = getInterrupt();
106 DPRINTF(Pl050, "Read Interrupts: %#x\n", getInterrupt());
107 break;
95 case kmiISR:
96 data = getInterrupt();
97 DPRINTF(Pl050, "Read Interrupts: %#x\n", getInterrupt());
98 break;
99
108 default:
109 if (readId(pkt, ambaId, pioAddr)) {
110 // Hack for variable size accesses
111 data = pkt->get<uint32_t>();
112 break;
113 }
114
115 warn("Tried to read PL050 at offset %#x that doesn't exist\n", daddr);

--- 31 unchanged lines hidden (view full) ---

147
148
149 switch (daddr) {
150 case kmiCr:
151 DPRINTF(Pl050, "Write Commmand: %#x\n", (uint32_t)pkt->get<uint8_t>());
152 control = pkt->get<uint8_t>();
153 updateIntStatus();
154 break;
100 default:
101 if (readId(pkt, ambaId, pioAddr)) {
102 // Hack for variable size accesses
103 data = pkt->get<uint32_t>();
104 break;
105 }
106
107 warn("Tried to read PL050 at offset %#x that doesn't exist\n", daddr);

--- 31 unchanged lines hidden (view full) ---

139
140
141 switch (daddr) {
142 case kmiCr:
143 DPRINTF(Pl050, "Write Commmand: %#x\n", (uint32_t)pkt->get<uint8_t>());
144 control = pkt->get<uint8_t>();
145 updateIntStatus();
146 break;
147
155 case kmiData:
156 DPRINTF(Pl050, "Write Data: %#x\n", (uint32_t)pkt->get<uint8_t>());
148 case kmiData:
149 DPRINTF(Pl050, "Write Data: %#x\n", (uint32_t)pkt->get<uint8_t>());
157 processCommand(pkt->get<uint8_t>());
150 ps2->hostWrite(pkt->get<uint8_t>());
158 updateIntStatus();
159 break;
151 updateIntStatus();
152 break;
153
160 case kmiClkDiv:
161 clkdiv = pkt->get<uint8_t>();
162 break;
154 case kmiClkDiv:
155 clkdiv = pkt->get<uint8_t>();
156 break;
157
163 default:
164 warn("Tried to write PL050 at offset %#x that doesn't exist\n", daddr);
165 break;
166 }
158 default:
159 warn("Tried to write PL050 at offset %#x that doesn't exist\n", daddr);
160 break;
161 }
162
167 pkt->makeAtomicResponse();
168 return pioDelay;
169}
170
163 pkt->makeAtomicResponse();
164 return pioDelay;
165}
166
171void
172Pl050::processCommand(uint8_t byte)
173{
174 using namespace Ps2;
175
167
176 if (ackNext) {
177 ackNext--;
178 rxQueue.push_back(Ack);
179 updateIntStatus();
180 return;
181 }
182
183 switch (byte) {
184 case Ps2Reset:
185 rxQueue.push_back(Ack);
186 rxQueue.push_back(SelfTestPass);
187 break;
188 case SetResolution:
189 case SetRate:
190 case SetStatusLed:
191 rxQueue.push_back(Ack);
192 ackNext = 1;
193 break;
194 case ReadId:
195 rxQueue.push_back(Ack);
196 if (params()->is_mouse)
197 rxQueue.push_back(MouseId);
198 else
199 rxQueue.push_back(KeyboardId);
200 break;
201 case TpReadId:
202 if (!params()->is_mouse)
203 break;
204 // We're not a trackpoint device, this should make the probe go away
205 rxQueue.push_back(Ack);
206 rxQueue.push_back(0);
207 rxQueue.push_back(0);
208 // fall through
209 case Disable:
210 case Enable:
211 case SetDefaults:
212 case SetScaling1_1:
213 case SetScaling1_2:
214 rxQueue.push_back(Ack);
215 break;
216 case StatusRequest:
217 rxQueue.push_back(Ack);
218 rxQueue.push_back(0);
219 rxQueue.push_back(2); // default resolution
220 rxQueue.push_back(100); // default sample rate
221 break;
222 case TouchKitId:
223 ackNext = 2;
224 rxQueue.push_back(Ack);
225 rxQueue.push_back(TouchKitId);
226 rxQueue.push_back(1);
227 rxQueue.push_back('A');
228
229 driverInitialized = true;
230 break;
231 default:
232 panic("Unknown byte received: %d\n", byte);
233 }
234
235 updateIntStatus();
236}
237
238
239void
240Pl050::updateIntStatus()
241{
242 const bool old_interrupt(getInterrupt());
243
168void
169Pl050::updateIntStatus()
170{
171 const bool old_interrupt(getInterrupt());
172
244 if (!rxQueue.empty())
245 rawInterrupts.rx = 1;
246 else
247 rawInterrupts.rx = 0;
173 rawInterrupts.rx = ps2->hostDataAvailable() ? 1 : 0;
248
249 if ((!old_interrupt && getInterrupt()) && !intEvent.scheduled()) {
250 schedule(intEvent, curTick() + intDelay);
251 } else if (old_interrupt && !(getInterrupt())) {
252 gic->clearInt(intNum);
253 }
254}
255
174
175 if ((!old_interrupt && getInterrupt()) && !intEvent.scheduled()) {
176 schedule(intEvent, curTick() + intDelay);
177 } else if (old_interrupt && !(getInterrupt())) {
178 gic->clearInt(intNum);
179 }
180}
181
182Pl050::InterruptReg
183Pl050::getInterrupt() const
184{
185 InterruptReg tmp_interrupt(0);
186
187 tmp_interrupt.tx = rawInterrupts.tx & control.txint_enable;
188 tmp_interrupt.rx = rawInterrupts.rx & control.rxint_enable;
189
190 return tmp_interrupt;
191}
192
256void
257Pl050::generateInterrupt()
258{
259 DPRINTF(Pl050, "Generate Interrupt: rawInt=%#x ctrl=%#x int=%#x\n",
260 rawInterrupts, control, getInterrupt());
261
262 if (getInterrupt()) {
263 gic->sendInt(intNum);
264 DPRINTF(Pl050, " -- Generated\n");
265 }
266}
267
268void
193void
194Pl050::generateInterrupt()
195{
196 DPRINTF(Pl050, "Generate Interrupt: rawInt=%#x ctrl=%#x int=%#x\n",
197 rawInterrupts, control, getInterrupt());
198
199 if (getInterrupt()) {
200 gic->sendInt(intNum);
201 DPRINTF(Pl050, " -- Generated\n");
202 }
203}
204
205void
269Pl050::mouseAt(uint16_t x, uint16_t y, uint8_t buttons)
270{
271 using namespace Ps2;
272
273 // If the driver hasn't initialized the device yet, no need to try and send
274 // it anything. Similarly we can get vnc mouse events orders of maginture
275 // faster than m5 can process them. Only queue up two sets mouse movements
276 // and don't add more until those are processed.
277 if (!driverInitialized || rxQueue.size() > 10)
278 return;
279
280 // We shouldn't be here unless a vnc server called us in which case
281 // we should have a pointer to it
282 assert(vnc);
283
284 // Convert screen coordinates to touchpad coordinates
285 uint16_t _x = (2047.0/vnc->videoWidth()) * x;
286 uint16_t _y = (2047.0/vnc->videoHeight()) * y;
287
288 rxQueue.push_back(buttons);
289 rxQueue.push_back(_x >> 7);
290 rxQueue.push_back(_x & 0x7f);
291 rxQueue.push_back(_y >> 7);
292 rxQueue.push_back(_y & 0x7f);
293
294 updateIntStatus();
295}
296
297
298void
299Pl050::keyPress(uint32_t key, bool down)
300{
301 using namespace Ps2;
302
303 std::list<uint8_t> keys;
304
305 // convert the X11 keysym into ps2 codes
306 keySymToPs2(key, down, shiftDown, keys);
307
308 // Insert into our queue of charecters
309 rxQueue.splice(rxQueue.end(), keys);
310 updateIntStatus();
311}
312
313void
314Pl050::serialize(CheckpointOut &cp) const
315{
316 uint8_t ctrlreg = control;
317 SERIALIZE_SCALAR(ctrlreg);
318
319 uint8_t stsreg = status;
320 SERIALIZE_SCALAR(stsreg);
321 SERIALIZE_SCALAR(clkdiv);
322
323 uint8_t raw_ints = rawInterrupts;
324 SERIALIZE_SCALAR(raw_ints);
206Pl050::serialize(CheckpointOut &cp) const
207{
208 uint8_t ctrlreg = control;
209 SERIALIZE_SCALAR(ctrlreg);
210
211 uint8_t stsreg = status;
212 SERIALIZE_SCALAR(stsreg);
213 SERIALIZE_SCALAR(clkdiv);
214
215 uint8_t raw_ints = rawInterrupts;
216 SERIALIZE_SCALAR(raw_ints);
325
326 SERIALIZE_SCALAR(ackNext);
327 SERIALIZE_SCALAR(shiftDown);
328 SERIALIZE_SCALAR(driverInitialized);
329
330 SERIALIZE_CONTAINER(rxQueue);
331}
332
333void
334Pl050::unserialize(CheckpointIn &cp)
335{
336 uint8_t ctrlreg;
337 UNSERIALIZE_SCALAR(ctrlreg);
338 control = ctrlreg;
339
340 uint8_t stsreg;
341 UNSERIALIZE_SCALAR(stsreg);
342 status = stsreg;
343
344 UNSERIALIZE_SCALAR(clkdiv);
345
346 uint8_t raw_ints;
347 UNSERIALIZE_SCALAR(raw_ints);
348 rawInterrupts = raw_ints;
217}
218
219void
220Pl050::unserialize(CheckpointIn &cp)
221{
222 uint8_t ctrlreg;
223 UNSERIALIZE_SCALAR(ctrlreg);
224 control = ctrlreg;
225
226 uint8_t stsreg;
227 UNSERIALIZE_SCALAR(stsreg);
228 status = stsreg;
229
230 UNSERIALIZE_SCALAR(clkdiv);
231
232 uint8_t raw_ints;
233 UNSERIALIZE_SCALAR(raw_ints);
234 rawInterrupts = raw_ints;
349
350 UNSERIALIZE_SCALAR(ackNext);
351 UNSERIALIZE_SCALAR(shiftDown);
352 UNSERIALIZE_SCALAR(driverInitialized);
353
354 UNSERIALIZE_CONTAINER(rxQueue);
355}
356
235}
236
357
358
359Pl050 *
360Pl050Params::create()
361{
362 return new Pl050(this);
363}
237Pl050 *
238Pl050Params::create()
239{
240 return new Pl050(this);
241}