gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
kmi.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 2017 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
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  * Authors: Ali Saidi
41  * William Wang
42  */
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 "mem/packet.hh"
52 #include "mem/packet_access.hh"
53 
55  : AmbaIntDevice(p, 0xfff), control(0), status(0x43), clkdiv(0),
56  rawInterrupts(0), ackNext(false), shiftDown(false),
57  vnc(p->vnc), driverInitialized(false), intEvent(this)
58 {
59  if (vnc) {
60  if (!p->is_mouse)
61  vnc->setKeyboard(this);
62  else
63  vnc->setMouse(this);
64  }
65 }
66 
67 Tick
69 {
70  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
71 
72  Addr daddr = pkt->getAddr() - pioAddr;
73 
74  uint32_t data = 0;
75 
76  switch (daddr) {
77  case kmiCr:
78  DPRINTF(Pl050, "Read Commmand: %#x\n", (uint32_t)control);
79  data = control;
80  break;
81  case kmiStat:
82  if (rxQueue.empty())
83  status.rxfull = 0;
84  else
85  status.rxfull = 1;
86 
87  DPRINTF(Pl050, "Read Status: %#x\n", (uint32_t)status);
88  data = status;
89  break;
90  case kmiData:
91  if (rxQueue.empty()) {
92  data = 0;
93  } else {
94  data = rxQueue.front();
95  rxQueue.pop_front();
96  }
97  DPRINTF(Pl050, "Read Data: %#x\n", (uint32_t)data);
99  break;
100  case kmiClkDiv:
101  data = clkdiv;
102  break;
103  case kmiISR:
104  data = getInterrupt();
105  DPRINTF(Pl050, "Read Interrupts: %#x\n", getInterrupt());
106  break;
107  default:
108  if (readId(pkt, ambaId, pioAddr)) {
109  // Hack for variable size accesses
110  data = pkt->get<uint32_t>();
111  break;
112  }
113 
114  warn("Tried to read PL050 at offset %#x that doesn't exist\n", daddr);
115  break;
116  }
117 
118  switch(pkt->getSize()) {
119  case 1:
120  pkt->set<uint8_t>(data);
121  break;
122  case 2:
123  pkt->set<uint16_t>(data);
124  break;
125  case 4:
126  pkt->set<uint32_t>(data);
127  break;
128  default:
129  panic("KMI read size too big?\n");
130  break;
131  }
132 
133  pkt->makeAtomicResponse();
134  return pioDelay;
135 }
136 
137 Tick
139 {
140 
141  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
142 
143  Addr daddr = pkt->getAddr() - pioAddr;
144 
145  assert(pkt->getSize() == sizeof(uint8_t));
146 
147 
148  switch (daddr) {
149  case kmiCr:
150  DPRINTF(Pl050, "Write Commmand: %#x\n", (uint32_t)pkt->get<uint8_t>());
151  control = pkt->get<uint8_t>();
152  updateIntStatus();
153  break;
154  case kmiData:
155  DPRINTF(Pl050, "Write Data: %#x\n", (uint32_t)pkt->get<uint8_t>());
156  processCommand(pkt->get<uint8_t>());
157  updateIntStatus();
158  break;
159  case kmiClkDiv:
160  clkdiv = pkt->get<uint8_t>();
161  break;
162  default:
163  warn("Tried to write PL050 at offset %#x that doesn't exist\n", daddr);
164  break;
165  }
166  pkt->makeAtomicResponse();
167  return pioDelay;
168 }
169 
170 void
172 {
173  using namespace Ps2;
174 
175  if (ackNext) {
176  ackNext--;
177  rxQueue.push_back(Ack);
178  updateIntStatus();
179  return;
180  }
181 
182  switch (byte) {
183  case Ps2Reset:
184  rxQueue.push_back(Ack);
185  rxQueue.push_back(SelfTestPass);
186  break;
187  case SetResolution:
188  case SetRate:
189  case SetStatusLed:
190  case SetScaling1_1:
191  case SetScaling1_2:
192  rxQueue.push_back(Ack);
193  ackNext = 1;
194  break;
195  case ReadId:
196  rxQueue.push_back(Ack);
197  if (params()->is_mouse)
198  rxQueue.push_back(MouseId);
199  else
200  rxQueue.push_back(KeyboardId);
201  break;
202  case TpReadId:
203  if (!params()->is_mouse)
204  break;
205  // We're not a trackpoint device, this should make the probe go away
206  rxQueue.push_back(Ack);
207  rxQueue.push_back(0);
208  rxQueue.push_back(0);
209  // fall through
210  case Disable:
211  case Enable:
212  case SetDefaults:
213  rxQueue.push_back(Ack);
214  break;
215  case StatusRequest:
216  rxQueue.push_back(Ack);
217  rxQueue.push_back(0);
218  rxQueue.push_back(2); // default resolution
219  rxQueue.push_back(100); // default sample rate
220  break;
221  case TouchKitId:
222  ackNext = 2;
223  rxQueue.push_back(Ack);
224  rxQueue.push_back(TouchKitId);
225  rxQueue.push_back(1);
226  rxQueue.push_back('A');
227 
228  driverInitialized = true;
229  break;
230  default:
231  panic("Unknown byte received: %d\n", byte);
232  }
233 
234  updateIntStatus();
235 }
236 
237 
238 void
240 {
241  const bool old_interrupt(getInterrupt());
242 
243  if (!rxQueue.empty())
244  rawInterrupts.rx = 1;
245  else
246  rawInterrupts.rx = 0;
247 
248  if ((!old_interrupt && getInterrupt()) && !intEvent.scheduled()) {
250  } else if (old_interrupt && !(getInterrupt())) {
251  gic->clearInt(intNum);
252  }
253 }
254 
255 void
257 {
258  DPRINTF(Pl050, "Generate Interrupt: rawInt=%#x ctrl=%#x int=%#x\n",
259  rawInterrupts, control, getInterrupt());
260 
261  if (getInterrupt()) {
262  gic->sendInt(intNum);
263  DPRINTF(Pl050, " -- Generated\n");
264  }
265 }
266 
267 void
268 Pl050::mouseAt(uint16_t x, uint16_t y, uint8_t buttons)
269 {
270  using namespace Ps2;
271 
272  // If the driver hasn't initialized the device yet, no need to try and send
273  // it anything. Similarly we can get vnc mouse events orders of maginture
274  // faster than m5 can process them. Only queue up two sets mouse movements
275  // and don't add more until those are processed.
276  if (!driverInitialized || rxQueue.size() > 10)
277  return;
278 
279  // We shouldn't be here unless a vnc server called us in which case
280  // we should have a pointer to it
281  assert(vnc);
282 
283  // Convert screen coordinates to touchpad coordinates
284  uint16_t _x = (2047.0/vnc->videoWidth()) * x;
285  uint16_t _y = (2047.0/vnc->videoHeight()) * y;
286 
287  rxQueue.push_back(buttons);
288  rxQueue.push_back(_x >> 7);
289  rxQueue.push_back(_x & 0x7f);
290  rxQueue.push_back(_y >> 7);
291  rxQueue.push_back(_y & 0x7f);
292 
293  updateIntStatus();
294 }
295 
296 
297 void
298 Pl050::keyPress(uint32_t key, bool down)
299 {
300  using namespace Ps2;
301 
303 
304  // convert the X11 keysym into ps2 codes
305  keySymToPs2(key, down, shiftDown, keys);
306 
307  // Insert into our queue of charecters
308  rxQueue.splice(rxQueue.end(), keys);
309  updateIntStatus();
310 }
311 
312 void
314 {
315  uint8_t ctrlreg = control;
316  SERIALIZE_SCALAR(ctrlreg);
317 
318  uint8_t stsreg = status;
319  SERIALIZE_SCALAR(stsreg);
321 
322  uint8_t raw_ints = rawInterrupts;
323  SERIALIZE_SCALAR(raw_ints);
324 
328 
330 }
331 
332 void
334 {
335  uint8_t ctrlreg;
336  UNSERIALIZE_SCALAR(ctrlreg);
337  control = ctrlreg;
338 
339  uint8_t stsreg;
340  UNSERIALIZE_SCALAR(stsreg);
341  status = stsreg;
342 
344 
345  uint8_t raw_ints;
346  UNSERIALIZE_SCALAR(raw_ints);
347  rawInterrupts = raw_ints;
348 
352 
354 }
355 
356 
357 
358 Pl050 *
359 Pl050Params::create()
360 {
361  return new Pl050(this);
362 }
#define DPRINTF(x,...)
Definition: trace.hh:212
Implementiation of a PL050 KMI.
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
virtual void clearInt(uint32_t num)=0
Clear an interrupt from a device that is connected to the GIC.
#define panic(...)
Definition: misc.hh:153
bool down
Definition: ps2.hh:92
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: kmi.cc:313
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:381
bool shiftDown
is the shift key currently down
Definition: kmi.hh:113
AmbaPioDeviceParams Params
Definition: amba_device.hh:84
const Params * params() const
Definition: kmi.hh:151
Definition: kmi.hh:57
static const int kmiClkDiv
Definition: kmi.hh:63
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
int ackNext
If the controller should ignore the next data byte and acknowledge it.
Definition: kmi.hh:110
const char data[]
Definition: circlebuf.cc:43
std::list< uint8_t > rxQueue
Receive queue.
Definition: kmi.hh:142
#define warn(...)
Definition: misc.hh:219
Bitfield< 5, 0 > status
Definition: miscregs.hh:1604
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: kmi.cc:68
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:164
Tick curTick()
The current simulated tick.
Definition: core.hh:47
Addr pioSize
Size that the device's address range.
Definition: io_device.hh:142
VncInput * vnc
The vnc server we're connected to (if any)
Definition: kmi.hh:116
void updateIntStatus()
Update the status of the interrupt registers and schedule an interrupt if required.
Definition: kmi.cc:239
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: kmi.cc:333
This is a base class for AMBA devices that have to respond to Device and Implementer ID calls...
virtual void sendInt(uint32_t num)=0
Post an interrupt from a device that is connected to the GIC.
void makeAtomicResponse()
Definition: packet.hh:857
uint64_t Tick
Tick count type.
Definition: types.hh:63
static const int kmiISR
Definition: kmi.hh:64
static const int kmiData
Definition: kmi.hh:62
void setKeyboard(VncKeyboard *_keyboard)
Set up the device that would like to receive notifications when keys are pressed in the vnc client ke...
Definition: vncinput.hh:171
void generateInterrupt()
Function to generate interrupt.
Definition: kmi.cc:256
Pl050(const Params *p)
Definition: kmi.cc:54
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:167
bool readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
Definition: amba_device.cc:74
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
uint64_t ambaId
Definition: amba_device.hh:81
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
void setMouse(VncMouse *_mouse)
Setup the device that would like to receive notifications when mouse movements or button presses are ...
Definition: vncinput.hh:177
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: kmi.cc:138
void keyPress(uint32_t key, bool down) override
Called when the vnc server receives a key press event from the client.
Definition: kmi.cc:298
InterruptReg getInterrupt() const
Get interrupt value.
Definition: kmi.hh:130
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
EventWrapper< Pl050,&Pl050::generateInterrupt > intEvent
Wrapper to create an event out of the thing.
Definition: kmi.hh:137
Declaration of a VNC input.
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:67
static const int kmiStat
Definition: kmi.hh:61
void processCommand(uint8_t byte)
Handle a command sent to the kmi and respond appropriately.
Definition: kmi.cc:171
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:145
uint8_t clkdiv
clock divisor register This register is just kept around to satisfy reads after driver does writes...
Definition: kmi.hh:97
void schedule(Event &event, Tick when)
Definition: eventq.hh:728
bool driverInitialized
If the linux driver has initialized the device yet and thus can we send mouse data.
Definition: kmi.hh:120
uint16_t videoWidth() const
What is the width of the screen we're displaying.
Definition: vncinput.hh:184
static const int kmiCr
Definition: kmi.hh:60
bool bool std::list< uint8_t > & keys
Definition: ps2.hh:92
void keySymToPs2(uint32_t key, bool down, bool &cur_shift, std::list< uint8_t > &keys)
Definition: ps2.cc:82
unsigned getSize() const
Definition: packet.hh:649
Definition: ps2.hh:63
Bitfield< 0 > p
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:139
Bitfield< 1 > x
Definition: types.hh:105
if(it_gpu==gpuTypeMap.end())
Definition: gpu_nomali.cc:75
BaseGic * gic
Definition: amba_device.hh:92
uint16_t videoHeight() const
What is the height of the screen we're displaying.
Definition: vncinput.hh:191
Addr getAddr() const
Definition: packet.hh:639
void mouseAt(uint16_t x, uint16_t y, uint8_t buttons) override
called whenever the mouse moves or it's button state changes buttons is a simple mask with each butto...
Definition: kmi.cc:268

Generated on Fri Jun 9 2017 13:03:45 for gem5 by doxygen 1.8.6