Only issue responses if we aren;t already blocked
[gem5.git] / src / dev / ide_ctrl.cc
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: Andrew Schultz
29 * Ali Saidi
30 * Miguel Serrano
31 */
32
33 #include <cstddef>
34 #include <cstdlib>
35 #include <string>
36 #include <vector>
37
38 #include "base/trace.hh"
39 #include "cpu/intr_control.hh"
40 #include "dev/ide_ctrl.hh"
41 #include "dev/ide_disk.hh"
42 #include "dev/pciconfigall.hh"
43 #include "dev/pcireg.h"
44 #include "dev/platform.hh"
45 #include "mem/packet.hh"
46 #include "sim/builder.hh"
47 #include "sim/sim_object.hh"
48 #include "sim/byteswap.hh"
49
50 using namespace std;
51
52 ////
53 // Initialization and destruction
54 ////
55
56 IdeController::IdeController(Params *p)
57 : PciDev(p)
58 {
59 // initialize the PIO interface addresses
60 pri_cmd_addr = 0;
61 pri_cmd_size = BARSize[0];
62
63 pri_ctrl_addr = 0;
64 pri_ctrl_size = BARSize[1];
65
66 sec_cmd_addr = 0;
67 sec_cmd_size = BARSize[2];
68
69 sec_ctrl_addr = 0;
70 sec_ctrl_size = BARSize[3];
71
72 // initialize the bus master interface (BMI) address to be configured
73 // via PCI
74 bmi_addr = 0;
75 bmi_size = BARSize[4];
76
77 // zero out all of the registers
78 memset(bmi_regs.data, 0, sizeof(bmi_regs));
79 memset(config_regs.data, 0, sizeof(config_regs.data));
80
81 // setup initial values
82 // enable both channels
83 config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN);
84 config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN);
85 bmi_regs.bmis0 = DMA1CAP | DMA0CAP;
86 bmi_regs.bmis1 = DMA1CAP | DMA0CAP;
87
88 // reset all internal variables
89 io_enabled = false;
90 bm_enabled = false;
91 memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
92
93 // setup the disks attached to controller
94 memset(disks, 0, sizeof(disks));
95 dev[0] = 0;
96 dev[1] = 0;
97
98 if (params()->disks.size() > 3)
99 panic("IDE controllers support a maximum of 4 devices attached!\n");
100
101 for (int i = 0; i < params()->disks.size(); i++) {
102 disks[i] = params()->disks[i];
103 disks[i]->setController(this);
104 }
105 }
106
107 IdeController::~IdeController()
108 {
109 for (int i = 0; i < 4; i++)
110 if (disks[i])
111 delete disks[i];
112 }
113
114 ////
115 // Utility functions
116 ///
117
118 void
119 IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
120 IdeRegType &reg_type)
121 {
122 offset = addr;
123
124 if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
125 offset -= pri_cmd_addr;
126 reg_type = COMMAND_BLOCK;
127 channel = PRIMARY;
128 } else if (addr >= pri_ctrl_addr &&
129 addr < (pri_ctrl_addr + pri_ctrl_size)) {
130 offset -= pri_ctrl_addr;
131 reg_type = CONTROL_BLOCK;
132 channel = PRIMARY;
133 } else if (addr >= sec_cmd_addr &&
134 addr < (sec_cmd_addr + sec_cmd_size)) {
135 offset -= sec_cmd_addr;
136 reg_type = COMMAND_BLOCK;
137 channel = SECONDARY;
138 } else if (addr >= sec_ctrl_addr &&
139 addr < (sec_ctrl_addr + sec_ctrl_size)) {
140 offset -= sec_ctrl_addr;
141 reg_type = CONTROL_BLOCK;
142 channel = SECONDARY;
143 } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
144 offset -= bmi_addr;
145 reg_type = BMI_BLOCK;
146 channel = (offset < BMIC1) ? PRIMARY : SECONDARY;
147 } else {
148 panic("IDE controller access to invalid address: %#x\n", addr);
149 }
150 }
151
152 int
153 IdeController::getDisk(IdeChannel channel)
154 {
155 int disk = 0;
156 uint8_t *devBit = &dev[0];
157
158 if (channel == SECONDARY) {
159 disk += 2;
160 devBit = &dev[1];
161 }
162
163 disk += *devBit;
164
165 assert(*devBit == 0 || *devBit == 1);
166
167 return disk;
168 }
169
170 int
171 IdeController::getDisk(IdeDisk *diskPtr)
172 {
173 for (int i = 0; i < 4; i++) {
174 if ((long)diskPtr == (long)disks[i])
175 return i;
176 }
177 return -1;
178 }
179
180 bool
181 IdeController::isDiskSelected(IdeDisk *diskPtr)
182 {
183 for (int i = 0; i < 4; i++) {
184 if ((long)diskPtr == (long)disks[i]) {
185 // is disk is on primary or secondary channel
186 int channel = i/2;
187 // is disk the master or slave
188 int devID = i%2;
189
190 return (dev[channel] == devID);
191 }
192 }
193 panic("Unable to find disk by pointer!!\n");
194 }
195
196 ////
197 // Command completion
198 ////
199
200 void
201 IdeController::setDmaComplete(IdeDisk *disk)
202 {
203 int diskNum = getDisk(disk);
204
205 if (diskNum < 0)
206 panic("Unable to find disk based on pointer %#x\n", disk);
207
208 if (diskNum < 2) {
209 // clear the start/stop bit in the command register
210 bmi_regs.bmic0 &= ~SSBM;
211 // clear the bus master active bit in the status register
212 bmi_regs.bmis0 &= ~BMIDEA;
213 // set the interrupt bit
214 bmi_regs.bmis0 |= IDEINTS;
215 } else {
216 // clear the start/stop bit in the command register
217 bmi_regs.bmic1 &= ~SSBM;
218 // clear the bus master active bit in the status register
219 bmi_regs.bmis1 &= ~BMIDEA;
220 // set the interrupt bit
221 bmi_regs.bmis1 |= IDEINTS;
222 }
223 }
224
225
226 ////
227 // Read and write handling
228 ////
229
230 Tick
231 IdeController::readConfig(Packet *pkt)
232 {
233 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
234 if (offset < PCI_DEVICE_SPECIFIC)
235 return PciDev::readConfig(pkt);
236 assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
237
238 pkt->allocate();
239
240 switch (pkt->getSize()) {
241 case sizeof(uint8_t):
242 switch (offset) {
243 case IDE_CTRL_CONF_DEV_TIMING:
244 pkt->set<uint8_t>(config_regs.sidetim);
245 break;
246 case IDE_CTRL_CONF_UDMA_CNTRL:
247 pkt->set<uint8_t>(config_regs.udmactl);
248 break;
249 case IDE_CTRL_CONF_PRIM_TIMING+1:
250 pkt->set<uint8_t>(htole(config_regs.idetim0) >> 8);
251 break;
252 case IDE_CTRL_CONF_SEC_TIMING+1:
253 pkt->set<uint8_t>(htole(config_regs.idetim1) >> 8);
254 break;
255 case IDE_CTRL_CONF_IDE_CONFIG:
256 pkt->set<uint8_t>(htole(config_regs.ideconfig) & 0xFF);
257 break;
258 case IDE_CTRL_CONF_IDE_CONFIG+1:
259 pkt->set<uint8_t>(htole(config_regs.ideconfig) >> 8);
260 break;
261 default:
262 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
263 offset);
264 }
265 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
266 (uint32_t)pkt->get<uint8_t>());
267 break;
268 case sizeof(uint16_t):
269 switch (offset) {
270 case IDE_CTRL_CONF_PRIM_TIMING:
271 pkt->set<uint16_t>(config_regs.idetim0);
272 break;
273 case IDE_CTRL_CONF_SEC_TIMING:
274 pkt->set<uint16_t>(config_regs.idetim1);
275 break;
276 case IDE_CTRL_CONF_UDMA_TIMING:
277 pkt->set<uint16_t>(config_regs.udmatim);
278 break;
279 case IDE_CTRL_CONF_IDE_CONFIG:
280 pkt->set<uint16_t>(config_regs.ideconfig);
281 break;
282 default:
283 panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
284 offset);
285 }
286 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
287 (uint32_t)pkt->get<uint16_t>());
288 break;
289 case sizeof(uint32_t):
290 panic("No 32bit reads implemented for this device.");
291 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset,
292 (uint32_t)pkt->get<uint32_t>());
293 break;
294 default:
295 panic("invalid access size(?) for PCI configspace!\n");
296 }
297 pkt->result = Packet::Success;
298 return configDelay;
299
300 }
301
302
303 Tick
304 IdeController::writeConfig(Packet *pkt)
305 {
306 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
307 if (offset < PCI_DEVICE_SPECIFIC) {
308 PciDev::writeConfig(pkt);
309 } else {
310 assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
311
312 switch (pkt->getSize()) {
313 case sizeof(uint8_t):
314 switch (offset) {
315 case IDE_CTRL_CONF_DEV_TIMING:
316 config_regs.sidetim = pkt->get<uint8_t>();
317 break;
318 case IDE_CTRL_CONF_UDMA_CNTRL:
319 config_regs.udmactl = pkt->get<uint8_t>();
320 break;
321 case IDE_CTRL_CONF_IDE_CONFIG:
322 config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) |
323 (pkt->get<uint8_t>());
324 break;
325 case IDE_CTRL_CONF_IDE_CONFIG+1:
326 config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) |
327 pkt->get<uint8_t>() << 8;
328 break;
329 default:
330 panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
331 offset);
332 }
333 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
334 offset, (uint32_t)pkt->get<uint8_t>());
335 break;
336 case sizeof(uint16_t):
337 switch (offset) {
338 case IDE_CTRL_CONF_PRIM_TIMING:
339 config_regs.idetim0 = pkt->get<uint16_t>();
340 break;
341 case IDE_CTRL_CONF_SEC_TIMING:
342 config_regs.idetim1 = pkt->get<uint16_t>();
343 break;
344 case IDE_CTRL_CONF_UDMA_TIMING:
345 config_regs.udmatim = pkt->get<uint16_t>();
346 break;
347 case IDE_CTRL_CONF_IDE_CONFIG:
348 config_regs.ideconfig = pkt->get<uint16_t>();
349 break;
350 default:
351 panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
352 offset);
353 }
354 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
355 offset, (uint32_t)pkt->get<uint16_t>());
356 break;
357 case sizeof(uint32_t):
358 panic("Write of unimplemented PCI config. register: %x\n", offset);
359 break;
360 default:
361 panic("invalid access size(?) for PCI configspace!\n");
362 }
363 }
364
365 /* Trap command register writes and enable IO/BM as appropriate as well as
366 * BARs. */
367 switch(offset) {
368 case PCI0_BASE_ADDR0:
369 if (BARAddrs[0] != 0)
370 pri_cmd_addr = BARAddrs[0];
371 break;
372
373 case PCI0_BASE_ADDR1:
374 if (BARAddrs[1] != 0)
375 pri_ctrl_addr = BARAddrs[1];
376 break;
377
378 case PCI0_BASE_ADDR2:
379 if (BARAddrs[2] != 0)
380 sec_cmd_addr = BARAddrs[2];
381 break;
382
383 case PCI0_BASE_ADDR3:
384 if (BARAddrs[3] != 0)
385 sec_ctrl_addr = BARAddrs[3];
386 break;
387
388 case PCI0_BASE_ADDR4:
389 if (BARAddrs[4] != 0)
390 bmi_addr = BARAddrs[4];
391 break;
392
393 case PCI_COMMAND:
394 if (letoh(config.command) & PCI_CMD_IOSE)
395 io_enabled = true;
396 else
397 io_enabled = false;
398
399 if (letoh(config.command) & PCI_CMD_BME)
400 bm_enabled = true;
401 else
402 bm_enabled = false;
403 break;
404 }
405 pkt->result = Packet::Success;
406 return configDelay;
407 }
408
409
410 Tick
411 IdeController::read(Packet *pkt)
412 {
413 Addr offset;
414 IdeChannel channel;
415 IdeRegType reg_type;
416 int disk;
417
418 pkt->allocate();
419 if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
420 panic("Bad IDE read size: %d\n", pkt->getSize());
421
422 parseAddr(pkt->getAddr(), offset, channel, reg_type);
423
424 if (!io_enabled) {
425 pkt->result = Packet::Success;
426 return pioDelay;
427 }
428
429 switch (reg_type) {
430 case BMI_BLOCK:
431 switch (pkt->getSize()) {
432 case sizeof(uint8_t):
433 pkt->set(bmi_regs.data[offset]);
434 break;
435 case sizeof(uint16_t):
436 pkt->set(*(uint16_t*)&bmi_regs.data[offset]);
437 break;
438 case sizeof(uint32_t):
439 pkt->set(*(uint32_t*)&bmi_regs.data[offset]);
440 break;
441 default:
442 panic("IDE read of BMI reg invalid size: %#x\n", pkt->getSize());
443 }
444 break;
445
446 case COMMAND_BLOCK:
447 case CONTROL_BLOCK:
448 disk = getDisk(channel);
449
450 if (disks[disk] == NULL) {
451 pkt->set<uint8_t>(0);
452 break;
453 }
454
455 switch (offset) {
456 case DATA_OFFSET:
457 switch (pkt->getSize()) {
458 case sizeof(uint16_t):
459 disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
460 break;
461
462 case sizeof(uint32_t):
463 disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
464 disks[disk]->read(offset, reg_type,
465 pkt->getPtr<uint8_t>() + sizeof(uint16_t));
466 break;
467
468 default:
469 panic("IDE read of data reg invalid size: %#x\n", pkt->getSize());
470 }
471 break;
472 default:
473 if (pkt->getSize() == sizeof(uint8_t)) {
474 disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
475 } else
476 panic("IDE read of command reg of invalid size: %#x\n", pkt->getSize());
477 }
478 break;
479 default:
480 panic("IDE controller read of unknown register block type!\n");
481 }
482 if (pkt->getSize() == 1)
483 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
484 offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>());
485 else if (pkt->getSize() == 2)
486 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
487 offset, pkt->getSize(), pkt->get<uint16_t>());
488 else
489 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
490 offset, pkt->getSize(), pkt->get<uint32_t>());
491
492 pkt->result = Packet::Success;
493 return pioDelay;
494 }
495
496 Tick
497 IdeController::write(Packet *pkt)
498 {
499 Addr offset;
500 IdeChannel channel;
501 IdeRegType reg_type;
502 int disk;
503 uint8_t oldVal, newVal;
504
505 parseAddr(pkt->getAddr(), offset, channel, reg_type);
506
507 if (!io_enabled) {
508 pkt->result = Packet::Success;
509 DPRINTF(IdeCtrl, "io not enabled\n");
510 return pioDelay;
511 }
512
513 switch (reg_type) {
514 case BMI_BLOCK:
515 if (!bm_enabled) {
516 pkt->result = Packet::Success;
517 return pioDelay;
518 }
519
520 switch (offset) {
521 // Bus master IDE command register
522 case BMIC1:
523 case BMIC0:
524 if (pkt->getSize() != sizeof(uint8_t))
525 panic("Invalid BMIC write size: %x\n", pkt->getSize());
526
527 // select the current disk based on DEV bit
528 disk = getDisk(channel);
529
530 oldVal = bmi_regs.chan[channel].bmic;
531 newVal = pkt->get<uint8_t>();
532
533 // if a DMA transfer is in progress, R/W control cannot change
534 if (oldVal & SSBM) {
535 if ((oldVal & RWCON) ^ (newVal & RWCON)) {
536 (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON;
537 }
538 }
539
540 // see if the start/stop bit is being changed
541 if ((oldVal & SSBM) ^ (newVal & SSBM)) {
542 if (oldVal & SSBM) {
543 // stopping DMA transfer
544 DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
545
546 // clear the BMIDEA bit
547 bmi_regs.chan[channel].bmis =
548 bmi_regs.chan[channel].bmis & ~BMIDEA;
549
550 if (disks[disk] == NULL)
551 panic("DMA stop for disk %d which does not exist\n",
552 disk);
553
554 // inform the disk of the DMA transfer abort
555 disks[disk]->abortDma();
556 } else {
557 // starting DMA transfer
558 DPRINTF(IdeCtrl, "Starting DMA transfer\n");
559
560 // set the BMIDEA bit
561 bmi_regs.chan[channel].bmis =
562 bmi_regs.chan[channel].bmis | BMIDEA;
563
564 if (disks[disk] == NULL)
565 panic("DMA start for disk %d which does not exist\n",
566 disk);
567
568 // inform the disk of the DMA transfer start
569 disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp));
570 }
571 }
572
573 // update the register value
574 bmi_regs.chan[channel].bmic = newVal;
575 break;
576
577 // Bus master IDE status register
578 case BMIS0:
579 case BMIS1:
580 if (pkt->getSize() != sizeof(uint8_t))
581 panic("Invalid BMIS write size: %x\n", pkt->getSize());
582
583 oldVal = bmi_regs.chan[channel].bmis;
584 newVal = pkt->get<uint8_t>();
585
586 // the BMIDEA bit is RO
587 newVal |= (oldVal & BMIDEA);
588
589 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
590 if ((oldVal & IDEINTS) && (newVal & IDEINTS))
591 newVal &= ~IDEINTS; // clear the interrupt?
592 else
593 (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS;
594
595 if ((oldVal & IDEDMAE) && (newVal & IDEDMAE))
596 newVal &= ~IDEDMAE;
597 else
598 (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE;
599
600 bmi_regs.chan[channel].bmis = newVal;
601 break;
602
603 // Bus master IDE descriptor table pointer register
604 case BMIDTP0:
605 case BMIDTP1:
606 {
607 if (pkt->getSize() != sizeof(uint32_t))
608 panic("Invalid BMIDTP write size: %x\n", pkt->getSize());
609
610 bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3);
611 }
612 break;
613
614 default:
615 if (pkt->getSize() != sizeof(uint8_t) &&
616 pkt->getSize() != sizeof(uint16_t) &&
617 pkt->getSize() != sizeof(uint32_t))
618 panic("IDE controller write of invalid write size: %x\n",
619 pkt->getSize());
620
621 // do a default copy of data into the registers
622 memcpy(&bmi_regs.data[offset], pkt->getPtr<uint8_t>(), pkt->getSize());
623 }
624 break;
625 case COMMAND_BLOCK:
626 if (offset == IDE_SELECT_OFFSET) {
627 uint8_t *devBit = &dev[channel];
628 *devBit = (letoh(pkt->get<uint8_t>()) & IDE_SELECT_DEV_BIT) ? 1 : 0;
629 }
630 // fall-through ok!
631 case CONTROL_BLOCK:
632 disk = getDisk(channel);
633
634 if (disks[disk] == NULL)
635 break;
636
637 switch (offset) {
638 case DATA_OFFSET:
639 switch (pkt->getSize()) {
640 case sizeof(uint16_t):
641 disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
642 break;
643
644 case sizeof(uint32_t):
645 disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
646 disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>() +
647 sizeof(uint16_t));
648 break;
649 default:
650 panic("IDE write of data reg invalid size: %#x\n", pkt->getSize());
651 }
652 break;
653 default:
654 if (pkt->getSize() == sizeof(uint8_t)) {
655 disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
656 } else
657 panic("IDE write of command reg of invalid size: %#x\n", pkt->getSize());
658 }
659 break;
660 default:
661 panic("IDE controller write of unknown register block type!\n");
662 }
663
664 if (pkt->getSize() == 1)
665 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
666 offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>());
667 else if (pkt->getSize() == 2)
668 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
669 offset, pkt->getSize(), pkt->get<uint16_t>());
670 else
671 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
672 offset, pkt->getSize(), pkt->get<uint32_t>());
673
674
675 pkt->result = Packet::Success;
676 return pioDelay;
677 }
678
679 ////
680 // Serialization
681 ////
682
683 void
684 IdeController::serialize(std::ostream &os)
685 {
686 // Serialize the PciDev base class
687 PciDev::serialize(os);
688
689 // Serialize register addresses and sizes
690 SERIALIZE_SCALAR(pri_cmd_addr);
691 SERIALIZE_SCALAR(pri_cmd_size);
692 SERIALIZE_SCALAR(pri_ctrl_addr);
693 SERIALIZE_SCALAR(pri_ctrl_size);
694 SERIALIZE_SCALAR(sec_cmd_addr);
695 SERIALIZE_SCALAR(sec_cmd_size);
696 SERIALIZE_SCALAR(sec_ctrl_addr);
697 SERIALIZE_SCALAR(sec_ctrl_size);
698 SERIALIZE_SCALAR(bmi_addr);
699 SERIALIZE_SCALAR(bmi_size);
700
701 // Serialize registers
702 SERIALIZE_ARRAY(bmi_regs.data,
703 sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
704 SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
705 SERIALIZE_ARRAY(config_regs.data,
706 sizeof(config_regs.data) / sizeof(config_regs.data[0]));
707
708 // Serialize internal state
709 SERIALIZE_SCALAR(io_enabled);
710 SERIALIZE_SCALAR(bm_enabled);
711 SERIALIZE_ARRAY(cmd_in_progress,
712 sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
713 }
714
715 void
716 IdeController::unserialize(Checkpoint *cp, const std::string &section)
717 {
718 // Unserialize the PciDev base class
719 PciDev::unserialize(cp, section);
720
721 // Unserialize register addresses and sizes
722 UNSERIALIZE_SCALAR(pri_cmd_addr);
723 UNSERIALIZE_SCALAR(pri_cmd_size);
724 UNSERIALIZE_SCALAR(pri_ctrl_addr);
725 UNSERIALIZE_SCALAR(pri_ctrl_size);
726 UNSERIALIZE_SCALAR(sec_cmd_addr);
727 UNSERIALIZE_SCALAR(sec_cmd_size);
728 UNSERIALIZE_SCALAR(sec_ctrl_addr);
729 UNSERIALIZE_SCALAR(sec_ctrl_size);
730 UNSERIALIZE_SCALAR(bmi_addr);
731 UNSERIALIZE_SCALAR(bmi_size);
732
733 // Unserialize registers
734 UNSERIALIZE_ARRAY(bmi_regs.data,
735 sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
736 UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
737 UNSERIALIZE_ARRAY(config_regs.data,
738 sizeof(config_regs.data) / sizeof(config_regs.data[0]));
739
740 // Unserialize internal state
741 UNSERIALIZE_SCALAR(io_enabled);
742 UNSERIALIZE_SCALAR(bm_enabled);
743 UNSERIALIZE_ARRAY(cmd_in_progress,
744 sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
745 }
746
747 #ifndef DOXYGEN_SHOULD_SKIP_THIS
748
749 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
750
751 SimObjectParam<System *> system;
752 SimObjectParam<Platform *> platform;
753 SimObjectParam<PciConfigData *> configdata;
754 Param<uint32_t> pci_bus;
755 Param<uint32_t> pci_dev;
756 Param<uint32_t> pci_func;
757 Param<Tick> pio_latency;
758 Param<Tick> config_latency;
759 SimObjectVectorParam<IdeDisk *> disks;
760
761 END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
762
763 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
764
765 INIT_PARAM(system, "System pointer"),
766 INIT_PARAM(platform, "Platform pointer"),
767 INIT_PARAM(configdata, "PCI Config data"),
768 INIT_PARAM(pci_bus, "PCI bus ID"),
769 INIT_PARAM(pci_dev, "PCI device number"),
770 INIT_PARAM(pci_func, "PCI function code"),
771 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
772 INIT_PARAM(config_latency, "Number of cycles for a config read or write"),
773 INIT_PARAM(disks, "IDE disks attached to this controller")
774
775 END_INIT_SIM_OBJECT_PARAMS(IdeController)
776
777 CREATE_SIM_OBJECT(IdeController)
778 {
779 IdeController::Params *params = new IdeController::Params;
780 params->name = getInstanceName();
781 params->platform = platform;
782 params->system = system;
783 params->configData = configdata;
784 params->busNum = pci_bus;
785 params->deviceNum = pci_dev;
786 params->functionNum = pci_func;
787 params->pio_delay = pio_latency;
788 params->config_delay = config_latency;
789 params->disks = disks;
790 return new IdeController(params);
791 }
792
793 REGISTER_SIM_OBJECT("IdeController", IdeController)
794
795 #endif //DOXYGEN_SHOULD_SKIP_THIS