gem5 v24.0.0.0
Loading...
Searching...
No Matches
ide_ctrl.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 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) 2004-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
42
43#include <string>
44
45#include "base/cprintf.hh"
46#include "debug/IdeCtrl.hh"
48#include "mem/packet.hh"
49#include "mem/packet_access.hh"
50#include "params/IdeController.hh"
51#include "sim/byteswap.hh"
52
53namespace gem5
54{
55
56// Bus master IDE registers
63
64IdeController::Channel::Channel(std::string new_name, IdeController *new_ctrl,
65 bool new_primary) :
66 Named(new_name), ctrl(new_ctrl), primary(new_primary)
67{
68 bmiRegs.reset();
69 bmiRegs.status.dmaCap0 = 1;
70 bmiRegs.status.dmaCap1 = 1;
71}
72
74 : PciDevice(p), configSpaceRegs(name() + ".config_space_regs"),
75 primary(name() + ".primary", this, true),
76 secondary(name() + ".secondary", this, false),
77 ioShift(p.io_shift), ctrlOffset(p.ctrl_offset)
78{
79 panic_if(params().disks.size() > 4,
80 "IDE controllers support a maximum of 4 devices attached!");
81
82 // Assign the disks to channels
83 for (int i = 0; i < params().disks.size(); i++) {
84 auto *disk = params().disks[i];
85 auto &channel = (i < 2) ? primary : secondary;
86
87 if (!disk)
88 continue;
89
90 if (i % 2 == 0)
91 channel.setDevice0(disk);
92 else
93 channel.setDevice1(disk);
94
95 // Arbitrarily set the chunk size to 4K.
96 disk->setChannel(&channel, 4 * 1024);
97 }
98
99 primary.select(false);
100 secondary.select(false);
101}
102
103void
104IdeController::ConfigSpaceRegs::serialize(CheckpointOut &cp) const
105{
106 SERIALIZE_SCALAR(primaryTiming);
107 SERIALIZE_SCALAR(secondaryTiming);
108 SERIALIZE_SCALAR(deviceTiming);
109 SERIALIZE_SCALAR(udmaControl);
110 SERIALIZE_SCALAR(udmaTiming);
111}
112
113void
114IdeController::ConfigSpaceRegs::unserialize(CheckpointIn &cp)
115{
116 UNSERIALIZE_SCALAR(primaryTiming);
117 UNSERIALIZE_SCALAR(secondaryTiming);
118 UNSERIALIZE_SCALAR(deviceTiming);
119 UNSERIALIZE_SCALAR(udmaControl);
120 UNSERIALIZE_SCALAR(udmaTiming);
121}
122
123void
130
131void
133{
134 bmiRegs.status.intStatus = 0;
135 _pendingInterrupt = false;
136 ctrl->clearInterrupt(isPrimary());
137}
138
139void
141{
142 auto &other = is_primary ? secondary : primary;
143 // If an interrupt isn't already posted for the other channel...
144 if (!other.pendingInterrupt())
146}
147
148void
150{
151 auto &other = is_primary ? secondary : primary;
152 // If the interrupt isn't still needed by the other channel...
153 if (!other.pendingInterrupt())
155}
156
157Tick
159{
160 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
162 return PciDevice::readConfig(pkt);
163
164 size_t size = pkt->getSize();
165
166 configSpaceRegs.read(offset, pkt->getPtr<void>(), size);
167
168 DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", offset, size,
169 pkt->getUintX(ByteOrder::little));
170
171 pkt->makeAtomicResponse();
172 return configDelay;
173}
174
175
176Tick
178{
179 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
180
182 return PciDevice::writeConfig(pkt);
183
184 size_t size = pkt->getSize();
185
186 DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
187 offset, size, pkt->getUintX(ByteOrder::little));
188
189 configSpaceRegs.write(offset, pkt->getConstPtr<void>(), size);
190
191 pkt->makeAtomicResponse();
192 return configDelay;
193}
194
195void
197 int size, uint8_t *data, bool read)
198{
199 const Addr SelectOffset = 6;
200 const uint8_t SelectDevBit = 0x10;
201
202 if (!read && offset == SelectOffset)
203 select(*data & SelectDevBit);
204
205 if (selected() == NULL) {
206 assert(size == sizeof(uint8_t));
207 *data = 0;
208 } else if (read) {
209 selected()->readCommand(offset, size, data);
210 } else {
211 selected()->writeCommand(offset, size, data);
212 }
213}
214
215void
217 int size, uint8_t *data, bool read)
218{
219 if (selected() == NULL) {
220 assert(size == sizeof(uint8_t));
221 *data = 0;
222 } else if (read) {
223 selected()->readControl(offset, size, data);
224 } else {
225 selected()->writeControl(offset, size, data);
226 }
227}
228
229void
231 int size, uint8_t *data, bool read)
232{
233 assert(offset + size <= sizeof(BMIRegs));
234 if (read) {
235 memcpy(data, (uint8_t *)&bmiRegs + offset, size);
236 } else {
237 switch (offset) {
238 case BMICommand:
239 {
240 if (size != sizeof(uint8_t))
241 panic("Invalid BMIC write size: %x\n", size);
242
243 BMICommandReg oldVal = bmiRegs.command;
244 BMICommandReg newVal = *data;
245
246 // if a DMA transfer is in progress, R/W control cannot change
247 if (oldVal.startStop && oldVal.rw != newVal.rw)
248 oldVal.rw = newVal.rw;
249
250 if (oldVal.startStop != newVal.startStop) {
251 if (selected() == NULL)
252 panic("DMA start for disk which does not exist\n");
253
254 if (oldVal.startStop) {
255 DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
256 bmiRegs.status.active = 0;
257
258 selected()->abortDma();
259 } else {
260 DPRINTF(IdeCtrl, "Starting DMA transfer\n");
261 bmiRegs.status.active = 1;
262
263 selected()->startDma(letoh(bmiRegs.bmidtp));
264 }
265 }
266
267 bmiRegs.command = newVal;
268 }
269 break;
270 case BMIStatus:
271 {
272 if (size != sizeof(uint8_t))
273 panic("Invalid BMIS write size: %x\n", size);
274
275 BMIStatusReg oldVal = bmiRegs.status;
276 BMIStatusReg newVal = *data;
277
278 // the BMIDEA bit is read only
279 newVal.active = oldVal.active;
280
281 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
282 if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) {
283 newVal.intStatus = 0; // clear the interrupt?
284 } else {
285 // Assigning two bitunion fields to each other does not
286 // work as intended, so we need to use this temporary
287 // variable to get around the bug.
288 uint8_t tmp = oldVal.intStatus;
289 newVal.intStatus = tmp;
290 }
291 if ((oldVal.dmaError == 1) && (newVal.dmaError == 1)) {
292 newVal.dmaError = 0;
293 } else {
294 uint8_t tmp = oldVal.dmaError;
295 newVal.dmaError = tmp;
296 }
297
298 bmiRegs.status = newVal;
299 }
300 break;
301 case BMIDescTablePtr:
302 if (size != sizeof(uint32_t))
303 panic("Invalid BMIDTP write size: %x\n", size);
304 bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3);
305 break;
306 default:
307 if (size != sizeof(uint8_t) && size != sizeof(uint16_t) &&
308 size != sizeof(uint32_t)) {
309 panic("IDE controller write of invalid size: %x\n", size);
310 }
311 memcpy((uint8_t *)&bmiRegs + offset, data, size);
312 }
313 }
314}
315
316void
318{
319 if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
320 panic("Bad IDE read size: %d\n", pkt->getSize());
321
322 Addr addr = pkt->getAddr();
323 int size = pkt->getSize();
324 uint8_t *dataPtr = pkt->getPtr<uint8_t>();
325
326 int bar_num;
327 Addr offset;
328 panic_if(!getBAR(addr, bar_num, offset),
329 "IDE controller access to invalid address: %#x.", addr);
330
331 switch (bar_num) {
332 case 0:
333 // linux may have shifted the address by ioShift,
334 // here we shift it back, similarly for ctrlOffset.
335 offset >>= ioShift;
336 primary.accessCommand(offset, size, dataPtr, read);
337 break;
338 case 1:
340 primary.accessControl(offset, size, dataPtr, read);
341 break;
342 case 2:
343 secondary.accessCommand(offset, size, dataPtr, read);
344 break;
345 case 3:
346 secondary.accessControl(offset, size, dataPtr, read);
347 break;
348 case 4:
349 {
350 PciCommandRegister command = letoh(config.command);
351 if (!read && !command.busMaster)
352 return;
353
354 if (offset < sizeof(Channel::BMIRegs)) {
355 primary.accessBMI(offset, size, dataPtr, read);
356 } else {
357 offset -= sizeof(Channel::BMIRegs);
358 secondary.accessBMI(offset, size, dataPtr, read);
359 }
360 }
361 }
362
363#ifndef NDEBUG
364 uint32_t data;
365 if (pkt->getSize() == 1)
366 data = pkt->getLE<uint8_t>();
367 else if (pkt->getSize() == 2)
368 data = pkt->getLE<uint16_t>();
369 else
370 data = pkt->getLE<uint32_t>();
371 DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n",
372 read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data);
373#endif
374
375 pkt->makeAtomicResponse();
376}
377
378void
380{
381 bmiRegs.command.startStop = 0;
382 bmiRegs.status.active = 0;
383 bmiRegs.status.intStatus = 1;
384}
385
386Tick
388{
389 dispatchAccess(pkt, true);
390 return pioDelay;
391}
392
393Tick
395{
396 dispatchAccess(pkt, false);
397 return pioDelay;
398}
399
400void
402{
403 // Serialize the PciDevice base class
405
406 // Serialize channels
407 primary.serialize("primary", cp);
408 secondary.serialize("secondary", cp);
409
410 // Serialize config registers
411 configSpaceRegs.serialize(cp);
412}
413
414void
416 CheckpointOut &cp) const
417{
418 uint8_t command = bmiRegs.command;
419 paramOut(cp, base + ".bmiRegs.command", command);
420 paramOut(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
421 uint8_t status = bmiRegs.status;
422 paramOut(cp, base + ".bmiRegs.status", status);
423 paramOut(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
424 paramOut(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
425 paramOut(cp, base + ".selectBit", selectBit);
426}
427
428void
430{
431 // Unserialize the PciDevice base class
433
434 // Unserialize channels
435 primary.unserialize("primary", cp);
436 secondary.unserialize("secondary", cp);
437
438 // Unserialize config registers
439 configSpaceRegs.unserialize(cp);
440}
441
442void
444{
445 uint8_t command;
446 paramIn(cp, base +".bmiRegs.command", command);
447 bmiRegs.command = command;
448 paramIn(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
449 uint8_t status;
450 paramIn(cp, base + ".bmiRegs.status", status);
451 bmiRegs.status = status;
452 paramIn(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
453 paramIn(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
454 paramIn(cp, base + ".selectBit", selectBit);
455 select(selectBit);
456}
457
458} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
DmaDeviceParams Params
void accessControl(Addr offset, int size, uint8_t *data, bool read)
Definition ide_ctrl.cc:216
void select(bool select_device_1)
Definition ide_ctrl.hh:169
void serialize(const std::string &base, std::ostream &os) const
Definition ide_ctrl.cc:415
void accessCommand(Addr offset, int size, uint8_t *data, bool read)
Definition ide_ctrl.cc:196
void setDevice0(IdeDisk *disk)
Definition ide_ctrl.hh:139
void accessBMI(Addr offset, int size, uint8_t *data, bool read)
Definition ide_ctrl.cc:230
void unserialize(const std::string &base, CheckpointIn &cp)
Definition ide_ctrl.cc:443
struct gem5::IdeController::Channel::BMIRegs bmiRegs
Channel(std::string new_name, IdeController *new_ctrl, bool new_primary)
Definition ide_ctrl.cc:64
Device model for an Intel PIIX4 IDE controller.
Definition ide_ctrl.hh:53
virtual void postInterrupt(bool is_primary)
Definition ide_ctrl.cc:140
virtual void clearInterrupt(bool is_primary)
Definition ide_ctrl.cc:149
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition ide_ctrl.cc:387
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition ide_ctrl.cc:394
IdeController(const Params &p)
Definition ide_ctrl.cc:73
EndBitUnion(BMICommandReg) class ConfigSpaceRegs ConfigSpaceRegs configSpaceRegs
Registers used in device specific PCI configuration.
Definition ide_ctrl.hh:67
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition ide_ctrl.cc:401
void dispatchAccess(PacketPtr pkt, bool read)
Definition ide_ctrl.cc:317
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition ide_ctrl.cc:429
Tick readConfig(PacketPtr pkt) override
Read from the PCI config space data that is stored locally.
Definition ide_ctrl.cc:158
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
Definition ide_ctrl.cc:177
Interface for things with names.
Definition named.hh:39
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
unsigned getSize() const
Definition packet.hh:817
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition packet.cc:352
const T * getConstPtr() const
Definition packet.hh:1234
void makeAtomicResponse()
Definition packet.hh:1074
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
PCI device, base implementation is only config space.
Definition device.hh:270
PCIConfig config
The current config space.
Definition device.hh:275
void intrClear()
Definition device.hh:365
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition device.cc:464
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition device.cc:401
bool getBAR(Addr addr, int &num, Addr &offs)
Which base address register (if any) maps the given address?
Definition device.hh:320
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
Definition device.cc:212
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition device.cc:283
void intrPost()
Definition device.hh:364
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
const Params & params() const
Device model for an IDE disk.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 5, 0 > status
Bitfield< 0 > p
Bitfield< 51, 12 > base
Definition pagetable.hh:141
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
T letoh(T value)
Definition byteswap.hh:173
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition types.cc:40
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition types.cc:72
BMIRegOffset
Definition ide_ctrl.cc:58
@ BMICommand
Definition ide_ctrl.cc:59
@ BMIDescTablePtr
Definition ide_ctrl.cc:61
@ BMIStatus
Definition ide_ctrl.cc:60
uint64_t Tick
Tick count type.
Definition types.hh:58
T htole(T value)
Definition byteswap.hh:172
Declaration of the Packet class.
#define PCI_DEVICE_SPECIFIC
Definition pcireg.h:164
#define PCI_CONFIG_SIZE
Definition pcireg.h:165
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
Simple PCI IDE controller with bus mastering capability and UDMA modeled after controller in the Inte...
Registers used for bus master interface.
Definition ide_ctrl.hh:154
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0