gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
i8259.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2005 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "dev/x86/i8259.hh"
30 
31 #include "base/bitfield.hh"
32 #include "base/trace.hh"
33 #include "debug/I8259.hh"
34 #include "dev/x86/i82094aa.hh"
35 #include "mem/packet.hh"
36 #include "mem/packet_access.hh"
37 
39  : BasicPioDevice(p, 2),
40  latency(p->pio_latency),
41  mode(p->mode), slave(p->slave),
42  IRR(0), ISR(0), IMR(0),
43  readIRR(true), initControlWord(0), autoEOI(false)
44 {
45  for (int i = 0; i < p->port_output_connection_count; i++) {
46  output.push_back(new IntSourcePin<I8259>(
47  csprintf("%s.output[%d]", name(), i), i, this));
48  }
49 
50  int in_count = p->port_inputs_connection_count;
51  panic_if(in_count >= NumLines,
52  "I8259 only supports 8 inputs, but there are %d.", in_count);
53  for (int i = 0; i < in_count; i++) {
54  inputs.push_back(new IntSinkPin<I8259>(
55  csprintf("%s.inputs[%d]", name(), i), i, this));
56  }
57 
58  for (bool &state: pinStates)
59  state = false;
60 }
61 
62 void
64 {
66 
67  for (auto *input: inputs)
68  pinStates[input->getId()] = input->state();
69 }
70 
71 Tick
73 {
74  assert(pkt->getSize() == 1);
75  switch(pkt->getAddr() - pioAddr)
76  {
77  case 0x0:
78  if (readIRR) {
79  DPRINTF(I8259, "Reading IRR as %#x.\n", IRR);
80  pkt->setLE(IRR);
81  } else {
82  DPRINTF(I8259, "Reading ISR as %#x.\n", ISR);
83  pkt->setLE(ISR);
84  }
85  break;
86  case 0x1:
87  DPRINTF(I8259, "Reading IMR as %#x.\n", IMR);
88  pkt->setLE(IMR);
89  break;
90  }
91  pkt->makeAtomicResponse();
92  return latency;
93 }
94 
95 Tick
97 {
98  assert(pkt->getSize() == 1);
99  uint8_t val = pkt->getLE<uint8_t>();
100  switch (pkt->getAddr() - pioAddr) {
101  case 0x0:
102  if (bits(val, 4)) {
103  DPRINTF(I8259, "Received initialization command word 1.\n");
104  IMR = 0;
105  edgeTriggered = bits(val, 3);
106  DPRINTF(I8259, "%s triggered mode.\n",
107  edgeTriggered ? "Edge" : "Level");
108  cascadeMode = !bits(val, 1);
109  DPRINTF(I8259, "%s mode.\n",
110  cascadeMode ? "Cascade" : "Single");
111  expectICW4 = bits(val, 0);
112  if (!expectICW4) {
113  autoEOI = false;
114  }
115  initControlWord = 1;
116  DPRINTF(I8259, "Expecting %d more bytes.\n", expectICW4 ? 3 : 2);
117  } else if (bits(val, 4, 3) == 0) {
118  DPRINTF(I8259, "Received operation command word 2.\n");
119  switch (bits(val, 7, 5)) {
120  case 0x0:
121  DPRINTF(I8259,
122  "Subcommand: Rotate in auto-EOI mode (clear).\n");
123  break;
124  case 0x1:
125  {
126  int line = findMsbSet(ISR);
127  DPRINTF(I8259, "Subcommand: Nonspecific EOI on line %d.\n",
128  line);
129  handleEOI(line);
130  }
131  break;
132  case 0x2:
133  DPRINTF(I8259, "Subcommand: No operation.\n");
134  break;
135  case 0x3:
136  {
137  int line = bits(val, 2, 0);
138  DPRINTF(I8259, "Subcommand: Specific EIO on line %d.\n",
139  line);
140  handleEOI(line);
141  }
142  break;
143  case 0x4:
144  DPRINTF(I8259, "Subcommand: Rotate in auto-EOI mode (set).\n");
145  break;
146  case 0x5:
147  DPRINTF(I8259, "Subcommand: Rotate on nonspecific EOI.\n");
148  break;
149  case 0x6:
150  DPRINTF(I8259, "Subcommand: Set priority command.\n");
151  DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n",
152  bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8);
153  break;
154  case 0x7:
155  DPRINTF(I8259, "Subcommand: Rotate on specific EOI.\n");
156  DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n",
157  bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8);
158  break;
159  }
160  } else if (bits(val, 4, 3) == 1) {
161  DPRINTF(I8259, "Received operation command word 3.\n");
162  if (bits(val, 7)) {
163  DPRINTF(I8259, "%s special mask mode.\n",
164  bits(val, 6) ? "Set" : "Clear");
165  }
166  if (bits(val, 1)) {
167  readIRR = bits(val, 0);
168  DPRINTF(I8259, "Read %s.\n", readIRR ? "IRR" : "ISR");
169  }
170  }
171  break;
172  case 0x1:
173  switch (initControlWord) {
174  case 0x0:
175  DPRINTF(I8259, "Received operation command word 1.\n");
176  DPRINTF(I8259, "Wrote IMR value %#x.\n", val);
177  IMR = val;
178  break;
179  case 0x1:
180  DPRINTF(I8259, "Received initialization command word 2.\n");
181  vectorOffset = val & ~mask(3);
182  DPRINTF(I8259, "Responsible for vectors %#x-%#x.\n",
184  if (cascadeMode) {
185  initControlWord++;
186  } else {
187  cascadeBits = 0;
188  initControlWord = 0;
189  }
190  break;
191  case 0x2:
192  DPRINTF(I8259, "Received initialization command word 3.\n");
193  if (mode == Enums::I8259Master) {
194  DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n",
195  bits(val, 0) ? " 0" : "",
196  bits(val, 1) ? " 1" : "",
197  bits(val, 2) ? " 2" : "",
198  bits(val, 3) ? " 3" : "",
199  bits(val, 4) ? " 4" : "",
200  bits(val, 5) ? " 5" : "",
201  bits(val, 6) ? " 6" : "",
202  bits(val, 7) ? " 7" : "");
203  cascadeBits = val;
204  } else {
205  DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3));
206  cascadeBits = val & mask(3);
207  }
208  if (expectICW4)
209  initControlWord++;
210  else
211  initControlWord = 0;
212  break;
213  case 0x3:
214  DPRINTF(I8259, "Received initialization command word 4.\n");
215  if (bits(val, 4)) {
216  DPRINTF(I8259, "Special fully nested mode.\n");
217  } else {
218  DPRINTF(I8259, "Not special fully nested mode.\n");
219  }
220  if (bits(val, 3) == 0) {
221  DPRINTF(I8259, "Nonbuffered.\n");
222  } else if (bits(val, 2) == 0) {
223  DPRINTF(I8259, "Buffered.\n");
224  } else {
225  DPRINTF(I8259, "Unrecognized buffer mode.\n");
226  }
227  autoEOI = bits(val, 1);
228  DPRINTF(I8259, "%s End Of Interrupt.\n",
229  autoEOI ? "Automatic" : "Normal");
230 
231  DPRINTF(I8259, "%s mode.\n", bits(val, 0) ? "80x86" : "MCX-80/85");
232  initControlWord = 0;
233  break;
234  }
235  break;
236  }
237  pkt->makeAtomicResponse();
238  return latency;
239 }
240 
241 void
243 {
244  ISR &= ~(1 << line);
245  // There may be an interrupt that was waiting which can
246  // now be sent.
247  if (IRR)
249 }
250 
251 void
253 {
254  if (bits(ISR, 7, line) == 0) {
255  if (!output.empty()) {
256  DPRINTF(I8259, "Propogating interrupt.\n");
257  for (auto *wire: output) {
258  wire->raise();
259  //XXX This is a hack.
260  wire->lower();
261  }
262  } else {
263  warn("Received interrupt but didn't have "
264  "anyone to tell about it.\n");
265  }
266  }
267 }
268 
269 void
271 {
272  DPRINTF(I8259, "Interrupt requested for line %d.\n", line);
273  if (line >= NumLines)
274  fatal("Line number %d doesn't exist. The max is %d.\n",
275  line, NumLines - 1);
276  if (bits(IMR, line)) {
277  DPRINTF(I8259, "Interrupt %d was masked.\n", line);
278  } else {
279  IRR |= 1 << line;
280  requestInterrupt(line);
281  }
282 }
283 
284 void
286 {
287  DPRINTF(I8259, "Interrupt signal raised for pin %d.\n", number);
288  if (number >= NumLines)
289  fatal("Line number %d doesn't exist. The max is %d.\n",
290  number, NumLines - 1);
291  if (!pinStates[number])
292  signalInterrupt(number);
293  pinStates[number] = true;
294 }
295 
296 void
298 {
299  DPRINTF(I8259, "Interrupt signal lowered for pin %d.\n", number);
300  if (number >= NumLines)
301  fatal("Line number %d doesn't exist. The max is %d.\n",
302  number, NumLines - 1);
303  pinStates[number] = false;
304 }
305 
306 int
308 {
309  /*
310  * This code only handles one slave. Since that's how the PC platform
311  * always uses the 8259 PIC, there shouldn't be any need for more. If
312  * there -is- a need for more for some reason, "slave" can become a
313  * vector of slaves.
314  */
315  int line = findMsbSet(IRR);
316  IRR &= ~(1 << line);
317  DPRINTF(I8259, "Interrupt %d was accepted.\n", line);
318  if (autoEOI) {
319  handleEOI(line);
320  } else {
321  ISR |= 1 << line;
322  }
323  if (slave && bits(cascadeBits, line)) {
324  DPRINTF(I8259, "Interrupt was from slave who will "
325  "provide the vector.\n");
326  return slave->getVector();
327  }
328  return line | vectorOffset;
329 }
330 
331 void
333 {
347 }
348 
349 void
351 {
365 }
366 
368 I8259Params::create()
369 {
370  return new X86ISA::I8259(this);
371 }
#define DPRINTF(x,...)
Definition: trace.hh:222
uint8_t IMR
Definition: i8259.hh:59
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8259.cc:96
Bitfield< 7 > i
I8259(Params *p)
Definition: i8259.cc:38
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8259.cc:350
Tick latency
Definition: i8259.hh:48
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8259.cc:72
I8259 * slave
Definition: i8259.hh:52
bool edgeTriggered
Definition: i8259.hh:69
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:56
PioDeviceParams Params
Definition: io_device.hh:131
bool cascadeMode
Definition: i8259.hh:64
Definition: cprintf.cc:40
Bitfield< 4, 0 > mode
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8259.cc:332
Bitfield< 63 > val
Definition: misc.hh:769
void setLE(T v)
Set the value in the data pointer to v as little endian.
bool autoEOI
Definition: i8259.hh:77
uint8_t cascadeBits
Definition: i8259.hh:67
unsigned getSize() const
Definition: packet.hh:730
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:770
uint8_t ISR
Definition: i8259.hh:57
void handleEOI(int line)
Definition: i8259.cc:242
std::vector< IntSinkPin< I8259 > * > inputs
Definition: i8259.hh:50
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
#define SERIALIZE_ENUM(scalar)
Definition: serialize.hh:786
void makeAtomicResponse()
Definition: packet.hh:943
uint64_t Tick
Tick count type.
Definition: types.hh:61
mask
Definition: misc.hh:796
Addr getAddr() const
Definition: packet.hh:720
static const int NumLines
Definition: i8259.hh:43
bool pinStates[NumLines]
Definition: i8259.hh:44
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:805
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:763
void raiseInterruptPin(int number)
Definition: i8259.cc:285
Enums::X86I8259CascadeMode mode
Definition: i8259.hh:51
virtual const std::string name() const
Definition: sim_object.hh:128
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:813
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:63
int getVector()
Definition: i8259.cc:307
#define UNSERIALIZE_ENUM(scalar)
Definition: serialize.hh:793
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: i8259.cc:63
int findMsbSet(uint64_t val)
Returns the bit position of the MSB that is set in the input.
Definition: bitfield.hh:203
uint8_t vectorOffset
Definition: i8259.hh:62
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
std::vector< IntSourcePin< I8259 > * > output
Definition: i8259.hh:49
bool expectICW4
Definition: i8259.hh:73
void signalInterrupt(int line)
Definition: i8259.cc:270
#define warn(...)
Definition: logging.hh:208
void lowerInterruptPin(int number)
Definition: i8259.cc:297
void requestInterrupt(int line)
Definition: i8259.cc:252
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71
bool readIRR
Definition: i8259.hh:70
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:181
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
uint8_t IRR
Definition: i8259.hh:55
int initControlWord
Definition: i8259.hh:74

Generated on Mon Jun 8 2020 15:45:11 for gem5 by doxygen 1.8.13