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