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