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 "sim/builder.hh"
47 #include "sim/sim_object.hh"
48 #include "sim/byteswap.hh"
53 // Initialization and destruction
56 IdeController::IdeController(Params
*p
)
59 // initialize the PIO interface addresses
61 pri_cmd_size
= BARSize
[0];
64 pri_ctrl_size
= BARSize
[1];
67 sec_cmd_size
= BARSize
[2];
70 sec_ctrl_size
= BARSize
[3];
72 // initialize the bus master interface (BMI) address to be configured
75 bmi_size
= BARSize
[4];
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
));
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
;
88 // reset all internal variables
91 memset(cmd_in_progress
, 0, sizeof(cmd_in_progress
));
93 // setup the disks attached to controller
94 memset(disks
, 0, sizeof(disks
));
98 if (params()->disks
.size() > 3)
99 panic("IDE controllers support a maximum of 4 devices attached!\n");
101 for (int i
= 0; i
< params()->disks
.size(); i
++) {
102 disks
[i
] = params()->disks
[i
];
103 disks
[i
]->setController(this);
107 IdeController::~IdeController()
109 for (int i
= 0; i
< 4; i
++)
119 IdeController::parseAddr(const Addr
&addr
, Addr
&offset
, IdeChannel
&channel
,
120 IdeRegType
®_type
)
124 if (addr
>= pri_cmd_addr
&& addr
< (pri_cmd_addr
+ pri_cmd_size
)) {
125 offset
-= pri_cmd_addr
;
126 reg_type
= COMMAND_BLOCK
;
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
;
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
;
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
;
143 } else if (addr
>= bmi_addr
&& addr
< (bmi_addr
+ bmi_size
)) {
145 reg_type
= BMI_BLOCK
;
146 channel
= (offset
< BMIC1
) ? PRIMARY
: SECONDARY
;
148 panic("IDE controller access to invalid address: %#x\n", addr
);
153 IdeController::getDisk(IdeChannel channel
)
156 uint8_t *devBit
= &dev
[0];
158 if (channel
== SECONDARY
) {
165 assert(*devBit
== 0 || *devBit
== 1);
171 IdeController::getDisk(IdeDisk
*diskPtr
)
173 for (int i
= 0; i
< 4; i
++) {
174 if ((long)diskPtr
== (long)disks
[i
])
181 IdeController::isDiskSelected(IdeDisk
*diskPtr
)
183 for (int i
= 0; i
< 4; i
++) {
184 if ((long)diskPtr
== (long)disks
[i
]) {
185 // is disk is on primary or secondary channel
187 // is disk the master or slave
190 return (dev
[channel
] == devID
);
193 panic("Unable to find disk by pointer!!\n");
197 // Command completion
201 IdeController::setDmaComplete(IdeDisk
*disk
)
203 int diskNum
= getDisk(disk
);
206 panic("Unable to find disk based on pointer %#x\n", disk
);
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
;
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
;
227 // Read and write handling
231 IdeController::readConfig(Packet
*pkt
)
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
);
240 switch (pkt
->getSize()) {
241 case sizeof(uint8_t):
243 case IDE_CTRL_CONF_DEV_TIMING
:
244 pkt
->set
<uint8_t>(config_regs
.sidetim
);
246 case IDE_CTRL_CONF_UDMA_CNTRL
:
247 pkt
->set
<uint8_t>(config_regs
.udmactl
);
249 case IDE_CTRL_CONF_PRIM_TIMING
+1:
250 pkt
->set
<uint8_t>(htole(config_regs
.idetim0
) >> 8);
252 case IDE_CTRL_CONF_SEC_TIMING
+1:
253 pkt
->set
<uint8_t>(htole(config_regs
.idetim1
) >> 8);
255 case IDE_CTRL_CONF_IDE_CONFIG
:
256 pkt
->set
<uint8_t>(htole(config_regs
.ideconfig
) & 0xFF);
258 case IDE_CTRL_CONF_IDE_CONFIG
+1:
259 pkt
->set
<uint8_t>(htole(config_regs
.ideconfig
) >> 8);
262 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
265 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 1 data: %#x\n", offset
,
266 (uint32_t)pkt
->get
<uint8_t>());
268 case sizeof(uint16_t):
270 case IDE_CTRL_CONF_PRIM_TIMING
:
271 pkt
->set
<uint16_t>(config_regs
.idetim0
);
273 case IDE_CTRL_CONF_SEC_TIMING
:
274 pkt
->set
<uint16_t>(config_regs
.idetim1
);
276 case IDE_CTRL_CONF_UDMA_TIMING
:
277 pkt
->set
<uint16_t>(config_regs
.udmatim
);
279 case IDE_CTRL_CONF_IDE_CONFIG
:
280 pkt
->set
<uint16_t>(config_regs
.ideconfig
);
283 panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
286 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 2 data: %#x\n", offset
,
287 (uint32_t)pkt
->get
<uint16_t>());
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>());
295 panic("invalid access size(?) for PCI configspace!\n");
297 pkt
->result
= Packet::Success
;
304 IdeController::writeConfig(Packet
*pkt
)
306 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
307 if (offset
< PCI_DEVICE_SPECIFIC
) {
308 PciDev::writeConfig(pkt
);
310 assert(offset
>= IDE_CTRL_CONF_START
&& (offset
+ 1) <= IDE_CTRL_CONF_END
);
312 switch (pkt
->getSize()) {
313 case sizeof(uint8_t):
315 case IDE_CTRL_CONF_DEV_TIMING
:
316 config_regs
.sidetim
= pkt
->get
<uint8_t>();
318 case IDE_CTRL_CONF_UDMA_CNTRL
:
319 config_regs
.udmactl
= pkt
->get
<uint8_t>();
321 case IDE_CTRL_CONF_IDE_CONFIG
:
322 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0xFF00) |
323 (pkt
->get
<uint8_t>());
325 case IDE_CTRL_CONF_IDE_CONFIG
+1:
326 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0x00FF) |
327 pkt
->get
<uint8_t>() << 8;
330 panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
333 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 1 data: %#x\n",
334 offset
, (uint32_t)pkt
->get
<uint8_t>());
336 case sizeof(uint16_t):
338 case IDE_CTRL_CONF_PRIM_TIMING
:
339 config_regs
.idetim0
= pkt
->get
<uint16_t>();
341 case IDE_CTRL_CONF_SEC_TIMING
:
342 config_regs
.idetim1
= pkt
->get
<uint16_t>();
344 case IDE_CTRL_CONF_UDMA_TIMING
:
345 config_regs
.udmatim
= pkt
->get
<uint16_t>();
347 case IDE_CTRL_CONF_IDE_CONFIG
:
348 config_regs
.ideconfig
= pkt
->get
<uint16_t>();
351 panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
354 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 2 data: %#x\n",
355 offset
, (uint32_t)pkt
->get
<uint16_t>());
357 case sizeof(uint32_t):
358 panic("Write of unimplemented PCI config. register: %x\n", offset
);
361 panic("invalid access size(?) for PCI configspace!\n");
365 /* Trap command register writes and enable IO/BM as appropriate as well as
368 case PCI0_BASE_ADDR0
:
369 if (BARAddrs
[0] != 0)
370 pri_cmd_addr
= BARAddrs
[0];
373 case PCI0_BASE_ADDR1
:
374 if (BARAddrs
[1] != 0)
375 pri_ctrl_addr
= BARAddrs
[1];
378 case PCI0_BASE_ADDR2
:
379 if (BARAddrs
[2] != 0)
380 sec_cmd_addr
= BARAddrs
[2];
383 case PCI0_BASE_ADDR3
:
384 if (BARAddrs
[3] != 0)
385 sec_ctrl_addr
= BARAddrs
[3];
388 case PCI0_BASE_ADDR4
:
389 if (BARAddrs
[4] != 0)
390 bmi_addr
= BARAddrs
[4];
394 if (letoh(config
.command
) & PCI_CMD_IOSE
)
399 if (letoh(config
.command
) & PCI_CMD_BME
)
405 pkt
->result
= Packet::Success
;
411 IdeController::read(Packet
*pkt
)
419 if (pkt
->getSize() != 1 && pkt
->getSize() != 2 && pkt
->getSize() !=4)
420 panic("Bad IDE read size: %d\n", pkt
->getSize());
422 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
425 pkt
->result
= Packet::Success
;
431 switch (pkt
->getSize()) {
432 case sizeof(uint8_t):
433 pkt
->set(bmi_regs
.data
[offset
]);
435 case sizeof(uint16_t):
436 pkt
->set(*(uint16_t*)&bmi_regs
.data
[offset
]);
438 case sizeof(uint32_t):
439 pkt
->set(*(uint32_t*)&bmi_regs
.data
[offset
]);
442 panic("IDE read of BMI reg invalid size: %#x\n", pkt
->getSize());
448 disk
= getDisk(channel
);
450 if (disks
[disk
] == NULL
) {
451 pkt
->set
<uint8_t>(0);
457 switch (pkt
->getSize()) {
458 case sizeof(uint16_t):
459 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
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));
469 panic("IDE read of data reg invalid size: %#x\n", pkt
->getSize());
473 if (pkt
->getSize() == sizeof(uint8_t)) {
474 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
476 panic("IDE read of command reg of invalid size: %#x\n", pkt
->getSize());
480 panic("IDE controller read of unknown register block type!\n");
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>());
489 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
490 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
492 pkt
->result
= Packet::Success
;
497 IdeController::write(Packet
*pkt
)
503 uint8_t oldVal
, newVal
;
505 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
508 pkt
->result
= Packet::Success
;
509 DPRINTF(IdeCtrl
, "io not enabled\n");
516 pkt
->result
= Packet::Success
;
521 // Bus master IDE command register
524 if (pkt
->getSize() != sizeof(uint8_t))
525 panic("Invalid BMIC write size: %x\n", pkt
->getSize());
527 // select the current disk based on DEV bit
528 disk
= getDisk(channel
);
530 oldVal
= bmi_regs
.chan
[channel
].bmic
;
531 newVal
= pkt
->get
<uint8_t>();
533 // if a DMA transfer is in progress, R/W control cannot change
535 if ((oldVal
& RWCON
) ^ (newVal
& RWCON
)) {
536 (oldVal
& RWCON
) ? newVal
|= RWCON
: newVal
&= ~RWCON
;
540 // see if the start/stop bit is being changed
541 if ((oldVal
& SSBM
) ^ (newVal
& SSBM
)) {
543 // stopping DMA transfer
544 DPRINTF(IdeCtrl
, "Stopping DMA transfer\n");
546 // clear the BMIDEA bit
547 bmi_regs
.chan
[channel
].bmis
=
548 bmi_regs
.chan
[channel
].bmis
& ~BMIDEA
;
550 if (disks
[disk
] == NULL
)
551 panic("DMA stop for disk %d which does not exist\n",
554 // inform the disk of the DMA transfer abort
555 disks
[disk
]->abortDma();
557 // starting DMA transfer
558 DPRINTF(IdeCtrl
, "Starting DMA transfer\n");
560 // set the BMIDEA bit
561 bmi_regs
.chan
[channel
].bmis
=
562 bmi_regs
.chan
[channel
].bmis
| BMIDEA
;
564 if (disks
[disk
] == NULL
)
565 panic("DMA start for disk %d which does not exist\n",
568 // inform the disk of the DMA transfer start
569 disks
[disk
]->startDma(letoh(bmi_regs
.chan
[channel
].bmidtp
));
573 // update the register value
574 bmi_regs
.chan
[channel
].bmic
= newVal
;
577 // Bus master IDE status register
580 if (pkt
->getSize() != sizeof(uint8_t))
581 panic("Invalid BMIS write size: %x\n", pkt
->getSize());
583 oldVal
= bmi_regs
.chan
[channel
].bmis
;
584 newVal
= pkt
->get
<uint8_t>();
586 // the BMIDEA bit is RO
587 newVal
|= (oldVal
& BMIDEA
);
589 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
590 if ((oldVal
& IDEINTS
) && (newVal
& IDEINTS
))
591 newVal
&= ~IDEINTS
; // clear the interrupt?
593 (oldVal
& IDEINTS
) ? newVal
|= IDEINTS
: newVal
&= ~IDEINTS
;
595 if ((oldVal
& IDEDMAE
) && (newVal
& IDEDMAE
))
598 (oldVal
& IDEDMAE
) ? newVal
|= IDEDMAE
: newVal
&= ~IDEDMAE
;
600 bmi_regs
.chan
[channel
].bmis
= newVal
;
603 // Bus master IDE descriptor table pointer register
607 if (pkt
->getSize() != sizeof(uint32_t))
608 panic("Invalid BMIDTP write size: %x\n", pkt
->getSize());
610 bmi_regs
.chan
[channel
].bmidtp
= htole(pkt
->get
<uint32_t>() & ~0x3);
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",
621 // do a default copy of data into the registers
622 memcpy(&bmi_regs
.data
[offset
], pkt
->getPtr
<uint8_t>(), pkt
->getSize());
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;
632 disk
= getDisk(channel
);
634 if (disks
[disk
] == NULL
)
639 switch (pkt
->getSize()) {
640 case sizeof(uint16_t):
641 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
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>() +
650 panic("IDE write of data reg invalid size: %#x\n", pkt
->getSize());
654 if (pkt
->getSize() == sizeof(uint8_t)) {
655 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
657 panic("IDE write of command reg of invalid size: %#x\n", pkt
->getSize());
661 panic("IDE controller write of unknown register block type!\n");
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>());
671 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
672 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
675 pkt
->result
= Packet::Success
;
684 IdeController::serialize(std::ostream
&os
)
686 // Serialize the PciDev base class
687 PciDev::serialize(os
);
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
);
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]));
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]));
716 IdeController::unserialize(Checkpoint
*cp
, const std::string
§ion
)
718 // Unserialize the PciDev base class
719 PciDev::unserialize(cp
, section
);
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
);
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]));
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]));
747 #ifndef DOXYGEN_SHOULD_SKIP_THIS
749 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
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
;
761 END_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
763 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController
)
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")
775 END_INIT_SIM_OBJECT_PARAMS(IdeController
)
777 CREATE_SIM_OBJECT(IdeController
)
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
);
793 REGISTER_SIM_OBJECT("IdeController", IdeController
)
795 #endif //DOXYGEN_SHOULD_SKIP_THIS