gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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  * Authors: Gabe Black
29  */
30 
31 #include "dev/x86/i8259.hh"
32 
33 #include "base/bitfield.hh"
34 #include "debug/I8259.hh"
35 #include "dev/x86/i82094aa.hh"
36 #include "mem/packet.hh"
37 #include "mem/packet_access.hh"
38 
40  : BasicPioDevice(p, 2), IntDevice(this),
41  latency(p->pio_latency), output(p->output),
42  mode(p->mode), slave(p->slave),
43  IRR(0), ISR(0), IMR(0),
44  readIRR(true), initControlWord(0), autoEOI(false)
45 {
46  for (int i = 0; i < NumLines; i++)
47  pinStates[i] = false;
48 }
49 
50 Tick
52 {
53  assert(pkt->getSize() == 1);
54  switch(pkt->getAddr() - pioAddr)
55  {
56  case 0x0:
57  if (readIRR) {
58  DPRINTF(I8259, "Reading IRR as %#x.\n", IRR);
59  pkt->set(IRR);
60  } else {
61  DPRINTF(I8259, "Reading ISR as %#x.\n", ISR);
62  pkt->set(ISR);
63  }
64  break;
65  case 0x1:
66  DPRINTF(I8259, "Reading IMR as %#x.\n", IMR);
67  pkt->set(IMR);
68  break;
69  }
70  pkt->makeAtomicResponse();
71  return latency;
72 }
73 
74 Tick
76 {
77  assert(pkt->getSize() == 1);
78  uint8_t val = pkt->get<uint8_t>();
79  switch (pkt->getAddr() - pioAddr) {
80  case 0x0:
81  if (bits(val, 4)) {
82  DPRINTF(I8259, "Received initialization command word 1.\n");
83  IMR = 0;
84  edgeTriggered = bits(val, 3);
85  DPRINTF(I8259, "%s triggered mode.\n",
86  edgeTriggered ? "Edge" : "Level");
87  cascadeMode = !bits(val, 1);
88  DPRINTF(I8259, "%s mode.\n",
89  cascadeMode ? "Cascade" : "Single");
90  expectICW4 = bits(val, 0);
91  if (!expectICW4) {
92  autoEOI = false;
93  }
94  initControlWord = 1;
95  DPRINTF(I8259, "Expecting %d more bytes.\n", expectICW4 ? 3 : 2);
96  } else if (bits(val, 4, 3) == 0) {
97  DPRINTF(I8259, "Received operation command word 2.\n");
98  switch (bits(val, 7, 5)) {
99  case 0x0:
100  DPRINTF(I8259,
101  "Subcommand: Rotate in auto-EOI mode (clear).\n");
102  break;
103  case 0x1:
104  {
105  int line = findMsbSet(ISR);
106  DPRINTF(I8259, "Subcommand: Nonspecific EOI on line %d.\n",
107  line);
108  handleEOI(line);
109  }
110  break;
111  case 0x2:
112  DPRINTF(I8259, "Subcommand: No operation.\n");
113  break;
114  case 0x3:
115  {
116  int line = bits(val, 2, 0);
117  DPRINTF(I8259, "Subcommand: Specific EIO on line %d.\n",
118  line);
119  handleEOI(line);
120  }
121  break;
122  case 0x4:
123  DPRINTF(I8259, "Subcommand: Rotate in auto-EOI mode (set).\n");
124  break;
125  case 0x5:
126  DPRINTF(I8259, "Subcommand: Rotate on nonspecific EOI.\n");
127  break;
128  case 0x6:
129  DPRINTF(I8259, "Subcommand: Set priority command.\n");
130  DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n",
131  bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8);
132  break;
133  case 0x7:
134  DPRINTF(I8259, "Subcommand: Rotate on specific EOI.\n");
135  DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n",
136  bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8);
137  break;
138  }
139  } else if (bits(val, 4, 3) == 1) {
140  DPRINTF(I8259, "Received operation command word 3.\n");
141  if (bits(val, 7)) {
142  DPRINTF(I8259, "%s special mask mode.\n",
143  bits(val, 6) ? "Set" : "Clear");
144  }
145  if (bits(val, 1)) {
146  readIRR = bits(val, 0);
147  DPRINTF(I8259, "Read %s.\n", readIRR ? "IRR" : "ISR");
148  }
149  }
150  break;
151  case 0x1:
152  switch (initControlWord) {
153  case 0x0:
154  DPRINTF(I8259, "Received operation command word 1.\n");
155  DPRINTF(I8259, "Wrote IMR value %#x.\n", val);
156  IMR = val;
157  break;
158  case 0x1:
159  DPRINTF(I8259, "Received initialization command word 2.\n");
160  vectorOffset = val & ~mask(3);
161  DPRINTF(I8259, "Responsible for vectors %#x-%#x.\n",
162  vectorOffset, vectorOffset | mask(3));
163  if (cascadeMode) {
164  initControlWord++;
165  } else {
166  cascadeBits = 0;
167  initControlWord = 0;
168  }
169  break;
170  case 0x2:
171  DPRINTF(I8259, "Received initialization command word 3.\n");
172  if (mode == Enums::I8259Master) {
173  DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n",
174  bits(val, 0) ? " 0" : "",
175  bits(val, 1) ? " 1" : "",
176  bits(val, 2) ? " 2" : "",
177  bits(val, 3) ? " 3" : "",
178  bits(val, 4) ? " 4" : "",
179  bits(val, 5) ? " 5" : "",
180  bits(val, 6) ? " 6" : "",
181  bits(val, 7) ? " 7" : "");
182  cascadeBits = val;
183  } else {
184  DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3));
185  cascadeBits = val & mask(3);
186  }
187  if (expectICW4)
188  initControlWord++;
189  else
190  initControlWord = 0;
191  break;
192  case 0x3:
193  DPRINTF(I8259, "Received initialization command word 4.\n");
194  if (bits(val, 4)) {
195  DPRINTF(I8259, "Special fully nested mode.\n");
196  } else {
197  DPRINTF(I8259, "Not special fully nested mode.\n");
198  }
199  if (bits(val, 3) == 0) {
200  DPRINTF(I8259, "Nonbuffered.\n");
201  } else if (bits(val, 2) == 0) {
202  DPRINTF(I8259, "Buffered.\n");
203  } else {
204  DPRINTF(I8259, "Unrecognized buffer mode.\n");
205  }
206  autoEOI = bits(val, 1);
207  DPRINTF(I8259, "%s End Of Interrupt.\n",
208  autoEOI ? "Automatic" : "Normal");
209 
210  DPRINTF(I8259, "%s mode.\n", bits(val, 0) ? "80x86" : "MCX-80/85");
211  initControlWord = 0;
212  break;
213  }
214  break;
215  }
216  pkt->makeAtomicResponse();
217  return latency;
218 }
219 
220 void
222 {
223  ISR &= ~(1 << line);
224  // There may be an interrupt that was waiting which can
225  // now be sent.
226  if (IRR)
227  requestInterrupt(findMsbSet(IRR));
228 }
229 
230 void
232 {
233  if (bits(ISR, 7, line) == 0) {
234  if (output) {
235  DPRINTF(I8259, "Propogating interrupt.\n");
236  output->raise();
237  //XXX This is a hack.
238  output->lower();
239  } else {
240  warn("Received interrupt but didn't have "
241  "anyone to tell about it.\n");
242  }
243  }
244 }
245 
246 void
248 {
249  DPRINTF(I8259, "Interrupt requested for line %d.\n", line);
250  if (line >= NumLines)
251  fatal("Line number %d doesn't exist. The max is %d.\n",
252  line, NumLines - 1);
253  if (bits(IMR, line)) {
254  DPRINTF(I8259, "Interrupt %d was masked.\n", line);
255  } else {
256  IRR |= 1 << line;
257  requestInterrupt(line);
258  }
259 }
260 
261 void
263 {
264  DPRINTF(I8259, "Interrupt signal raised for pin %d.\n", number);
265  if (number >= NumLines)
266  fatal("Line number %d doesn't exist. The max is %d.\n",
267  number, NumLines - 1);
268  if (!pinStates[number])
269  signalInterrupt(number);
270  pinStates[number] = true;
271 }
272 
273 void
275 {
276  DPRINTF(I8259, "Interrupt signal lowered for pin %d.\n", number);
277  if (number >= NumLines)
278  fatal("Line number %d doesn't exist. The max is %d.\n",
279  number, NumLines - 1);
280  pinStates[number] = false;
281 }
282 
283 int
285 {
286  /*
287  * This code only handles one slave. Since that's how the PC platform
288  * always uses the 8259 PIC, there shouldn't be any need for more. If
289  * there -is- a need for more for some reason, "slave" can become a
290  * vector of slaves.
291  */
292  int line = findMsbSet(IRR);
293  IRR &= ~(1 << line);
294  DPRINTF(I8259, "Interrupt %d was accepted.\n", line);
295  if (autoEOI) {
296  handleEOI(line);
297  } else {
298  ISR |= 1 << line;
299  }
300  if (slave && bits(cascadeBits, line)) {
301  DPRINTF(I8259, "Interrupt was from slave who will "
302  "provide the vector.\n");
303  return slave->getVector();
304  }
305  return line | vectorOffset;
306 }
307 
308 void
310 {
311  SERIALIZE_ARRAY(pinStates, NumLines);
313  SERIALIZE_SCALAR(IRR);
316  SERIALIZE_SCALAR(vectorOffset);
317  SERIALIZE_SCALAR(cascadeMode);
318  SERIALIZE_SCALAR(cascadeBits);
319  SERIALIZE_SCALAR(edgeTriggered);
320  SERIALIZE_SCALAR(readIRR);
321  SERIALIZE_SCALAR(expectICW4);
322  SERIALIZE_SCALAR(initControlWord);
323  SERIALIZE_SCALAR(autoEOI);
324 }
325 
326 void
328 {
329  UNSERIALIZE_ARRAY(pinStates, NumLines);
331  UNSERIALIZE_SCALAR(IRR);
334  UNSERIALIZE_SCALAR(vectorOffset);
335  UNSERIALIZE_SCALAR(cascadeMode);
336  UNSERIALIZE_SCALAR(cascadeBits);
337  UNSERIALIZE_SCALAR(edgeTriggered);
338  UNSERIALIZE_SCALAR(readIRR);
339  UNSERIALIZE_SCALAR(expectICW4);
340  UNSERIALIZE_SCALAR(initControlWord);
341  UNSERIALIZE_SCALAR(autoEOI);
342 }
343 
345 I8259Params::create()
346 {
347  return new X86ISA::I8259(this);
348 }
#define DPRINTF(x,...)
Definition: trace.hh:212
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8259.cc:75
static void output(const char *filename)
Definition: debug.cc:63
Bitfield< 7 > i
Definition: miscregs.hh:1378
I8259(Params *p)
Definition: i8259.cc:39
void lowerInterruptPin(int number) override
Definition: i8259.cc:274
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8259.cc:327
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8259.cc:51
PioDeviceParams Params
Definition: io_device.hh:116
Bitfield< 4, 0 > mode
Definition: miscregs.hh:1385
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8259.cc:309
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
Bitfield< 63 > val
Definition: misc.hh:770
#define warn(...)
Definition: misc.hh:219
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
void handleEOI(int line)
Definition: i8259.cc:221
void raiseInterruptPin(int number) override
Definition: i8259.cc:262
void makeAtomicResponse()
Definition: packet.hh:857
uint64_t Tick
Tick count type.
Definition: types.hh:63
mask
Definition: misc.hh:797
#define fatal(...)
Definition: misc.hh:163
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
static const int NumLines
Definition: i8259.hh:45
bool pinStates[NumLines]
Definition: i8259.hh:46
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
#define UNSERIALIZE_ENUM(scalar)
Definition: serialize.hh:151
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:67
int getVector()
Definition: i8259.cc:284
int findMsbSet(uint64_t val)
Returns the bit position of the MSB that is set in the input.
Definition: bitfield.hh:163
void signalInterrupt(int line) override
Definition: i8259.cc:247
unsigned getSize() const
Definition: packet.hh:649
void requestInterrupt(int line)
Definition: i8259.cc:231
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
Definition: bitfield.hh:67
Bitfield< 0 > p
#define SERIALIZE_ENUM(scalar)
Definition: serialize.hh:149
Addr getAddr() const
Definition: packet.hh:639

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