2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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.
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.
28 * Authors: Andrew Schultz
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 "mem/packet_access.hh"
47 #include "sim/builder.hh"
48 #include "sim/sim_object.hh"
49 #include "sim/byteswap.hh"
54 // Initialization and destruction
57 IdeController::IdeController(Params
*p
)
60 // initialize the PIO interface addresses
62 pri_cmd_size
= BARSize
[0];
65 pri_ctrl_size
= BARSize
[1];
68 sec_cmd_size
= BARSize
[2];
71 sec_ctrl_size
= BARSize
[3];
73 // initialize the bus master interface (BMI) address to be configured
76 bmi_size
= BARSize
[4];
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
));
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
;
89 // reset all internal variables
92 memset(cmd_in_progress
, 0, sizeof(cmd_in_progress
));
94 // setup the disks attached to controller
95 memset(disks
, 0, sizeof(disks
));
99 if (params()->disks
.size() > 3)
100 panic("IDE controllers support a maximum of 4 devices attached!\n");
102 for (int i
= 0; i
< params()->disks
.size(); i
++) {
103 disks
[i
] = params()->disks
[i
];
104 disks
[i
]->setController(this);
108 IdeController::~IdeController()
110 for (int i
= 0; i
< 4; i
++)
120 IdeController::parseAddr(const Addr
&addr
, Addr
&offset
, IdeChannel
&channel
,
121 IdeRegType
®_type
)
125 if (addr
>= pri_cmd_addr
&& addr
< (pri_cmd_addr
+ pri_cmd_size
)) {
126 offset
-= pri_cmd_addr
;
127 reg_type
= COMMAND_BLOCK
;
129 } else if (addr
>= pri_ctrl_addr
&&
130 addr
< (pri_ctrl_addr
+ pri_ctrl_size
)) {
131 offset
-= pri_ctrl_addr
;
132 reg_type
= CONTROL_BLOCK
;
134 } else if (addr
>= sec_cmd_addr
&&
135 addr
< (sec_cmd_addr
+ sec_cmd_size
)) {
136 offset
-= sec_cmd_addr
;
137 reg_type
= COMMAND_BLOCK
;
139 } else if (addr
>= sec_ctrl_addr
&&
140 addr
< (sec_ctrl_addr
+ sec_ctrl_size
)) {
141 offset
-= sec_ctrl_addr
;
142 reg_type
= CONTROL_BLOCK
;
144 } else if (addr
>= bmi_addr
&& addr
< (bmi_addr
+ bmi_size
)) {
146 reg_type
= BMI_BLOCK
;
147 channel
= (offset
< BMIC1
) ? PRIMARY
: SECONDARY
;
149 panic("IDE controller access to invalid address: %#x\n", addr
);
154 IdeController::getDisk(IdeChannel channel
)
157 uint8_t *devBit
= &dev
[0];
159 if (channel
== SECONDARY
) {
166 assert(*devBit
== 0 || *devBit
== 1);
172 IdeController::getDisk(IdeDisk
*diskPtr
)
174 for (int i
= 0; i
< 4; i
++) {
175 if ((long)diskPtr
== (long)disks
[i
])
182 IdeController::isDiskSelected(IdeDisk
*diskPtr
)
184 for (int i
= 0; i
< 4; i
++) {
185 if ((long)diskPtr
== (long)disks
[i
]) {
186 // is disk is on primary or secondary channel
188 // is disk the master or slave
191 return (dev
[channel
] == devID
);
194 panic("Unable to find disk by pointer!!\n");
198 // Command completion
202 IdeController::setDmaComplete(IdeDisk
*disk
)
204 int diskNum
= getDisk(disk
);
207 panic("Unable to find disk based on pointer %#x\n", disk
);
210 // clear the start/stop bit in the command register
211 bmi_regs
.bmic0
&= ~SSBM
;
212 // clear the bus master active bit in the status register
213 bmi_regs
.bmis0
&= ~BMIDEA
;
214 // set the interrupt bit
215 bmi_regs
.bmis0
|= IDEINTS
;
217 // clear the start/stop bit in the command register
218 bmi_regs
.bmic1
&= ~SSBM
;
219 // clear the bus master active bit in the status register
220 bmi_regs
.bmis1
&= ~BMIDEA
;
221 // set the interrupt bit
222 bmi_regs
.bmis1
|= IDEINTS
;
228 // Read and write handling
232 IdeController::readConfig(PacketPtr pkt
)
234 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
235 if (offset
< PCI_DEVICE_SPECIFIC
)
236 return PciDev::readConfig(pkt
);
237 assert(offset
>= IDE_CTRL_CONF_START
&& (offset
+ 1) <= IDE_CTRL_CONF_END
);
241 switch (pkt
->getSize()) {
242 case sizeof(uint8_t):
244 case IDE_CTRL_CONF_DEV_TIMING
:
245 pkt
->set
<uint8_t>(config_regs
.sidetim
);
247 case IDE_CTRL_CONF_UDMA_CNTRL
:
248 pkt
->set
<uint8_t>(config_regs
.udmactl
);
250 case IDE_CTRL_CONF_PRIM_TIMING
+1:
251 pkt
->set
<uint8_t>(htole(config_regs
.idetim0
) >> 8);
253 case IDE_CTRL_CONF_SEC_TIMING
+1:
254 pkt
->set
<uint8_t>(htole(config_regs
.idetim1
) >> 8);
256 case IDE_CTRL_CONF_IDE_CONFIG
:
257 pkt
->set
<uint8_t>(htole(config_regs
.ideconfig
) & 0xFF);
259 case IDE_CTRL_CONF_IDE_CONFIG
+1:
260 pkt
->set
<uint8_t>(htole(config_regs
.ideconfig
) >> 8);
263 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
266 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 1 data: %#x\n", offset
,
267 (uint32_t)pkt
->get
<uint8_t>());
269 case sizeof(uint16_t):
271 case IDE_CTRL_CONF_PRIM_TIMING
:
272 pkt
->set
<uint16_t>(config_regs
.idetim0
);
274 case IDE_CTRL_CONF_SEC_TIMING
:
275 pkt
->set
<uint16_t>(config_regs
.idetim1
);
277 case IDE_CTRL_CONF_UDMA_TIMING
:
278 pkt
->set
<uint16_t>(config_regs
.udmatim
);
280 case IDE_CTRL_CONF_IDE_CONFIG
:
281 pkt
->set
<uint16_t>(config_regs
.ideconfig
);
284 panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
287 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 2 data: %#x\n", offset
,
288 (uint32_t)pkt
->get
<uint16_t>());
290 case sizeof(uint32_t):
291 panic("No 32bit reads implemented for this device.");
292 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 4 data: %#x\n", offset
,
293 (uint32_t)pkt
->get
<uint32_t>());
296 panic("invalid access size(?) for PCI configspace!\n");
298 pkt
->result
= Packet::Success
;
305 IdeController::writeConfig(PacketPtr pkt
)
307 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
308 if (offset
< PCI_DEVICE_SPECIFIC
) {
309 PciDev::writeConfig(pkt
);
311 assert(offset
>= IDE_CTRL_CONF_START
&& (offset
+ 1) <= IDE_CTRL_CONF_END
);
313 switch (pkt
->getSize()) {
314 case sizeof(uint8_t):
316 case IDE_CTRL_CONF_DEV_TIMING
:
317 config_regs
.sidetim
= pkt
->get
<uint8_t>();
319 case IDE_CTRL_CONF_UDMA_CNTRL
:
320 config_regs
.udmactl
= pkt
->get
<uint8_t>();
322 case IDE_CTRL_CONF_IDE_CONFIG
:
323 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0xFF00) |
324 (pkt
->get
<uint8_t>());
326 case IDE_CTRL_CONF_IDE_CONFIG
+1:
327 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0x00FF) |
328 pkt
->get
<uint8_t>() << 8;
331 panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
334 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 1 data: %#x\n",
335 offset
, (uint32_t)pkt
->get
<uint8_t>());
337 case sizeof(uint16_t):
339 case IDE_CTRL_CONF_PRIM_TIMING
:
340 config_regs
.idetim0
= pkt
->get
<uint16_t>();
342 case IDE_CTRL_CONF_SEC_TIMING
:
343 config_regs
.idetim1
= pkt
->get
<uint16_t>();
345 case IDE_CTRL_CONF_UDMA_TIMING
:
346 config_regs
.udmatim
= pkt
->get
<uint16_t>();
348 case IDE_CTRL_CONF_IDE_CONFIG
:
349 config_regs
.ideconfig
= pkt
->get
<uint16_t>();
352 panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
355 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 2 data: %#x\n",
356 offset
, (uint32_t)pkt
->get
<uint16_t>());
358 case sizeof(uint32_t):
359 panic("Write of unimplemented PCI config. register: %x\n", offset
);
362 panic("invalid access size(?) for PCI configspace!\n");
366 /* Trap command register writes and enable IO/BM as appropriate as well as
369 case PCI0_BASE_ADDR0
:
370 if (BARAddrs
[0] != 0)
371 pri_cmd_addr
= BARAddrs
[0];
374 case PCI0_BASE_ADDR1
:
375 if (BARAddrs
[1] != 0)
376 pri_ctrl_addr
= BARAddrs
[1];
379 case PCI0_BASE_ADDR2
:
380 if (BARAddrs
[2] != 0)
381 sec_cmd_addr
= BARAddrs
[2];
384 case PCI0_BASE_ADDR3
:
385 if (BARAddrs
[3] != 0)
386 sec_ctrl_addr
= BARAddrs
[3];
389 case PCI0_BASE_ADDR4
:
390 if (BARAddrs
[4] != 0)
391 bmi_addr
= BARAddrs
[4];
395 if (letoh(config
.command
) & PCI_CMD_IOSE
)
400 if (letoh(config
.command
) & PCI_CMD_BME
)
406 pkt
->result
= Packet::Success
;
412 IdeController::read(PacketPtr pkt
)
420 if (pkt
->getSize() != 1 && pkt
->getSize() != 2 && pkt
->getSize() !=4)
421 panic("Bad IDE read size: %d\n", pkt
->getSize());
423 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
426 pkt
->result
= Packet::Success
;
432 switch (pkt
->getSize()) {
433 case sizeof(uint8_t):
434 pkt
->set(bmi_regs
.data
[offset
]);
436 case sizeof(uint16_t):
437 pkt
->set(*(uint16_t*)&bmi_regs
.data
[offset
]);
439 case sizeof(uint32_t):
440 pkt
->set(*(uint32_t*)&bmi_regs
.data
[offset
]);
443 panic("IDE read of BMI reg invalid size: %#x\n", pkt
->getSize());
449 disk
= getDisk(channel
);
451 if (disks
[disk
] == NULL
) {
452 pkt
->set
<uint8_t>(0);
458 switch (pkt
->getSize()) {
459 case sizeof(uint16_t):
460 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
463 case sizeof(uint32_t):
464 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
465 disks
[disk
]->read(offset
, reg_type
,
466 pkt
->getPtr
<uint8_t>() + sizeof(uint16_t));
470 panic("IDE read of data reg invalid size: %#x\n", pkt
->getSize());
474 if (pkt
->getSize() == sizeof(uint8_t)) {
475 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
477 panic("IDE read of command reg of invalid size: %#x\n", pkt
->getSize());
481 panic("IDE controller read of unknown register block type!\n");
483 if (pkt
->getSize() == 1)
484 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
485 offset
, pkt
->getSize(), (uint32_t)pkt
->get
<uint8_t>());
486 else if (pkt
->getSize() == 2)
487 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
488 offset
, pkt
->getSize(), pkt
->get
<uint16_t>());
490 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
491 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
493 pkt
->result
= Packet::Success
;
498 IdeController::write(PacketPtr pkt
)
504 uint8_t oldVal
, newVal
;
506 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
509 pkt
->result
= Packet::Success
;
510 DPRINTF(IdeCtrl
, "io not enabled\n");
517 pkt
->result
= Packet::Success
;
522 // Bus master IDE command register
525 if (pkt
->getSize() != sizeof(uint8_t))
526 panic("Invalid BMIC write size: %x\n", pkt
->getSize());
528 // select the current disk based on DEV bit
529 disk
= getDisk(channel
);
531 oldVal
= bmi_regs
.chan
[channel
].bmic
;
532 newVal
= pkt
->get
<uint8_t>();
534 // if a DMA transfer is in progress, R/W control cannot change
536 if ((oldVal
& RWCON
) ^ (newVal
& RWCON
)) {
537 (oldVal
& RWCON
) ? newVal
|= RWCON
: newVal
&= ~RWCON
;
541 // see if the start/stop bit is being changed
542 if ((oldVal
& SSBM
) ^ (newVal
& SSBM
)) {
544 // stopping DMA transfer
545 DPRINTF(IdeCtrl
, "Stopping DMA transfer\n");
547 // clear the BMIDEA bit
548 bmi_regs
.chan
[channel
].bmis
=
549 bmi_regs
.chan
[channel
].bmis
& ~BMIDEA
;
551 if (disks
[disk
] == NULL
)
552 panic("DMA stop for disk %d which does not exist\n",
555 // inform the disk of the DMA transfer abort
556 disks
[disk
]->abortDma();
558 // starting DMA transfer
559 DPRINTF(IdeCtrl
, "Starting DMA transfer\n");
561 // set the BMIDEA bit
562 bmi_regs
.chan
[channel
].bmis
=
563 bmi_regs
.chan
[channel
].bmis
| BMIDEA
;
565 if (disks
[disk
] == NULL
)
566 panic("DMA start for disk %d which does not exist\n",
569 // inform the disk of the DMA transfer start
570 disks
[disk
]->startDma(letoh(bmi_regs
.chan
[channel
].bmidtp
));
574 // update the register value
575 bmi_regs
.chan
[channel
].bmic
= newVal
;
578 // Bus master IDE status register
581 if (pkt
->getSize() != sizeof(uint8_t))
582 panic("Invalid BMIS write size: %x\n", pkt
->getSize());
584 oldVal
= bmi_regs
.chan
[channel
].bmis
;
585 newVal
= pkt
->get
<uint8_t>();
587 // the BMIDEA bit is RO
588 newVal
|= (oldVal
& BMIDEA
);
590 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
591 if ((oldVal
& IDEINTS
) && (newVal
& IDEINTS
))
592 newVal
&= ~IDEINTS
; // clear the interrupt?
594 (oldVal
& IDEINTS
) ? newVal
|= IDEINTS
: newVal
&= ~IDEINTS
;
596 if ((oldVal
& IDEDMAE
) && (newVal
& IDEDMAE
))
599 (oldVal
& IDEDMAE
) ? newVal
|= IDEDMAE
: newVal
&= ~IDEDMAE
;
601 bmi_regs
.chan
[channel
].bmis
= newVal
;
604 // Bus master IDE descriptor table pointer register
608 if (pkt
->getSize() != sizeof(uint32_t))
609 panic("Invalid BMIDTP write size: %x\n", pkt
->getSize());
611 bmi_regs
.chan
[channel
].bmidtp
= htole(pkt
->get
<uint32_t>() & ~0x3);
616 if (pkt
->getSize() != sizeof(uint8_t) &&
617 pkt
->getSize() != sizeof(uint16_t) &&
618 pkt
->getSize() != sizeof(uint32_t))
619 panic("IDE controller write of invalid write size: %x\n",
622 // do a default copy of data into the registers
623 memcpy(&bmi_regs
.data
[offset
], pkt
->getPtr
<uint8_t>(), pkt
->getSize());
627 if (offset
== IDE_SELECT_OFFSET
) {
628 uint8_t *devBit
= &dev
[channel
];
629 *devBit
= (letoh(pkt
->get
<uint8_t>()) & IDE_SELECT_DEV_BIT
) ? 1 : 0;
633 disk
= getDisk(channel
);
635 if (disks
[disk
] == NULL
)
640 switch (pkt
->getSize()) {
641 case sizeof(uint16_t):
642 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
645 case sizeof(uint32_t):
646 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
647 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>() +
651 panic("IDE write of data reg invalid size: %#x\n", pkt
->getSize());
655 if (pkt
->getSize() == sizeof(uint8_t)) {
656 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
658 panic("IDE write of command reg of invalid size: %#x\n", pkt
->getSize());
662 panic("IDE controller write of unknown register block type!\n");
665 if (pkt
->getSize() == 1)
666 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
667 offset
, pkt
->getSize(), (uint32_t)pkt
->get
<uint8_t>());
668 else if (pkt
->getSize() == 2)
669 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
670 offset
, pkt
->getSize(), pkt
->get
<uint16_t>());
672 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
673 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
676 pkt
->result
= Packet::Success
;
685 IdeController::serialize(std::ostream
&os
)
687 // Serialize the PciDev base class
688 PciDev::serialize(os
);
690 // Serialize register addresses and sizes
691 SERIALIZE_SCALAR(pri_cmd_addr
);
692 SERIALIZE_SCALAR(pri_cmd_size
);
693 SERIALIZE_SCALAR(pri_ctrl_addr
);
694 SERIALIZE_SCALAR(pri_ctrl_size
);
695 SERIALIZE_SCALAR(sec_cmd_addr
);
696 SERIALIZE_SCALAR(sec_cmd_size
);
697 SERIALIZE_SCALAR(sec_ctrl_addr
);
698 SERIALIZE_SCALAR(sec_ctrl_size
);
699 SERIALIZE_SCALAR(bmi_addr
);
700 SERIALIZE_SCALAR(bmi_size
);
702 // Serialize registers
703 SERIALIZE_ARRAY(bmi_regs
.data
,
704 sizeof(bmi_regs
.data
) / sizeof(bmi_regs
.data
[0]));
705 SERIALIZE_ARRAY(dev
, sizeof(dev
) / sizeof(dev
[0]));
706 SERIALIZE_ARRAY(config_regs
.data
,
707 sizeof(config_regs
.data
) / sizeof(config_regs
.data
[0]));
709 // Serialize internal state
710 SERIALIZE_SCALAR(io_enabled
);
711 SERIALIZE_SCALAR(bm_enabled
);
712 SERIALIZE_ARRAY(cmd_in_progress
,
713 sizeof(cmd_in_progress
) / sizeof(cmd_in_progress
[0]));
717 IdeController::unserialize(Checkpoint
*cp
, const std::string
§ion
)
719 // Unserialize the PciDev base class
720 PciDev::unserialize(cp
, section
);
722 // Unserialize register addresses and sizes
723 UNSERIALIZE_SCALAR(pri_cmd_addr
);
724 UNSERIALIZE_SCALAR(pri_cmd_size
);
725 UNSERIALIZE_SCALAR(pri_ctrl_addr
);
726 UNSERIALIZE_SCALAR(pri_ctrl_size
);
727 UNSERIALIZE_SCALAR(sec_cmd_addr
);
728 UNSERIALIZE_SCALAR(sec_cmd_size
);
729 UNSERIALIZE_SCALAR(sec_ctrl_addr
);
730 UNSERIALIZE_SCALAR(sec_ctrl_size
);
731 UNSERIALIZE_SCALAR(bmi_addr
);
732 UNSERIALIZE_SCALAR(bmi_size
);
734 // Unserialize registers
735 UNSERIALIZE_ARRAY(bmi_regs
.data
,
736 sizeof(bmi_regs
.data
) / sizeof(bmi_regs
.data
[0]));
737 UNSERIALIZE_ARRAY(dev
, sizeof(dev
) / sizeof(dev
[0]));
738 UNSERIALIZE_ARRAY(config_regs
.data
,
739 sizeof(config_regs
.data
) / sizeof(config_regs
.data
[0]));
741 // Unserialize internal state
742 UNSERIALIZE_SCALAR(io_enabled
);
743 UNSERIALIZE_SCALAR(bm_enabled
);
744 UNSERIALIZE_ARRAY(cmd_in_progress
,
745 sizeof(cmd_in_progress
) / sizeof(cmd_in_progress
[0]));
748 #ifndef DOXYGEN_SHOULD_SKIP_THIS
750 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
752 SimObjectParam
<System
*> system
;
753 SimObjectParam
<Platform
*> platform
;
754 SimObjectParam
<PciConfigData
*> configdata
;
755 Param
<uint32_t> pci_bus
;
756 Param
<uint32_t> pci_dev
;
757 Param
<uint32_t> pci_func
;
758 Param
<Tick
> pio_latency
;
759 Param
<Tick
> config_latency
;
760 SimObjectVectorParam
<IdeDisk
*> disks
;
762 END_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
764 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController
)
766 INIT_PARAM(system
, "System pointer"),
767 INIT_PARAM(platform
, "Platform pointer"),
768 INIT_PARAM(configdata
, "PCI Config data"),
769 INIT_PARAM(pci_bus
, "PCI bus ID"),
770 INIT_PARAM(pci_dev
, "PCI device number"),
771 INIT_PARAM(pci_func
, "PCI function code"),
772 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
773 INIT_PARAM(config_latency
, "Number of cycles for a config read or write"),
774 INIT_PARAM(disks
, "IDE disks attached to this controller")
776 END_INIT_SIM_OBJECT_PARAMS(IdeController
)
778 CREATE_SIM_OBJECT(IdeController
)
780 IdeController::Params
*params
= new IdeController::Params
;
781 params
->name
= getInstanceName();
782 params
->platform
= platform
;
783 params
->system
= system
;
784 params
->configData
= configdata
;
785 params
->busNum
= pci_bus
;
786 params
->deviceNum
= pci_dev
;
787 params
->functionNum
= pci_func
;
788 params
->pio_delay
= pio_latency
;
789 params
->config_delay
= config_latency
;
790 params
->disks
= disks
;
791 return new IdeController(params
);
794 REGISTER_SIM_OBJECT("IdeController", IdeController
)
796 #endif //DOXYGEN_SHOULD_SKIP_THIS