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
);
239 assert(offset
>= IDE_CTRL_CONF_START
&& (offset
+ 1) <= IDE_CTRL_CONF_END
);
243 switch (pkt
->getSize()) {
244 case sizeof(uint8_t):
246 case IDE_CTRL_CONF_DEV_TIMING
:
247 pkt
->set
<uint8_t>(config_regs
.sidetim
);
249 case IDE_CTRL_CONF_UDMA_CNTRL
:
250 pkt
->set
<uint8_t>(config_regs
.udmactl
);
252 case IDE_CTRL_CONF_PRIM_TIMING
+1:
253 pkt
->set
<uint8_t>(htole(config_regs
.idetim0
) >> 8);
255 case IDE_CTRL_CONF_SEC_TIMING
+1:
256 pkt
->set
<uint8_t>(htole(config_regs
.idetim1
) >> 8);
258 case IDE_CTRL_CONF_IDE_CONFIG
:
259 pkt
->set
<uint8_t>(htole(config_regs
.ideconfig
) & 0xFF);
261 case IDE_CTRL_CONF_IDE_CONFIG
+1:
262 pkt
->set
<uint8_t>(htole(config_regs
.ideconfig
) >> 8);
265 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
268 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 1 data: %#x\n", offset
,
269 (uint32_t)pkt
->get
<uint8_t>());
271 case sizeof(uint16_t):
273 case IDE_CTRL_CONF_PRIM_TIMING
:
274 pkt
->set
<uint16_t>(config_regs
.idetim0
);
276 case IDE_CTRL_CONF_SEC_TIMING
:
277 pkt
->set
<uint16_t>(config_regs
.idetim1
);
279 case IDE_CTRL_CONF_UDMA_TIMING
:
280 pkt
->set
<uint16_t>(config_regs
.udmatim
);
282 case IDE_CTRL_CONF_IDE_CONFIG
:
283 pkt
->set
<uint16_t>(config_regs
.ideconfig
);
286 panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
289 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 2 data: %#x\n", offset
,
290 (uint32_t)pkt
->get
<uint16_t>());
292 case sizeof(uint32_t):
293 panic("No 32bit reads implemented for this device.");
294 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 4 data: %#x\n", offset
,
295 (uint32_t)pkt
->get
<uint32_t>());
298 panic("invalid access size(?) for PCI configspace!\n");
300 pkt
->makeAtomicResponse();
306 IdeController::writeConfig(PacketPtr pkt
)
308 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
309 if (offset
< PCI_DEVICE_SPECIFIC
) {
310 PciDev::writeConfig(pkt
);
312 assert(offset
>= IDE_CTRL_CONF_START
&& (offset
+ 1) <= IDE_CTRL_CONF_END
);
314 switch (pkt
->getSize()) {
315 case sizeof(uint8_t):
317 case IDE_CTRL_CONF_DEV_TIMING
:
318 config_regs
.sidetim
= pkt
->get
<uint8_t>();
320 case IDE_CTRL_CONF_UDMA_CNTRL
:
321 config_regs
.udmactl
= pkt
->get
<uint8_t>();
323 case IDE_CTRL_CONF_IDE_CONFIG
:
324 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0xFF00) |
325 (pkt
->get
<uint8_t>());
327 case IDE_CTRL_CONF_IDE_CONFIG
+1:
328 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0x00FF) |
329 pkt
->get
<uint8_t>() << 8;
332 panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
335 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 1 data: %#x\n",
336 offset
, (uint32_t)pkt
->get
<uint8_t>());
338 case sizeof(uint16_t):
340 case IDE_CTRL_CONF_PRIM_TIMING
:
341 config_regs
.idetim0
= pkt
->get
<uint16_t>();
343 case IDE_CTRL_CONF_SEC_TIMING
:
344 config_regs
.idetim1
= pkt
->get
<uint16_t>();
346 case IDE_CTRL_CONF_UDMA_TIMING
:
347 config_regs
.udmatim
= pkt
->get
<uint16_t>();
349 case IDE_CTRL_CONF_IDE_CONFIG
:
350 config_regs
.ideconfig
= pkt
->get
<uint16_t>();
353 panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
356 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 2 data: %#x\n",
357 offset
, (uint32_t)pkt
->get
<uint16_t>());
359 case sizeof(uint32_t):
360 panic("Write of unimplemented PCI config. register: %x\n", offset
);
363 panic("invalid access size(?) for PCI configspace!\n");
365 pkt
->makeAtomicResponse();
368 /* Trap command register writes and enable IO/BM as appropriate as well as
371 case PCI0_BASE_ADDR0
:
372 if (BARAddrs
[0] != 0)
373 pri_cmd_addr
= BARAddrs
[0];
376 case PCI0_BASE_ADDR1
:
377 if (BARAddrs
[1] != 0)
378 pri_ctrl_addr
= BARAddrs
[1];
381 case PCI0_BASE_ADDR2
:
382 if (BARAddrs
[2] != 0)
383 sec_cmd_addr
= BARAddrs
[2];
386 case PCI0_BASE_ADDR3
:
387 if (BARAddrs
[3] != 0)
388 sec_ctrl_addr
= BARAddrs
[3];
391 case PCI0_BASE_ADDR4
:
392 if (BARAddrs
[4] != 0)
393 bmi_addr
= BARAddrs
[4];
397 if (letoh(config
.command
) & PCI_CMD_IOSE
)
402 if (letoh(config
.command
) & PCI_CMD_BME
)
413 IdeController::read(PacketPtr pkt
)
421 if (pkt
->getSize() != 1 && pkt
->getSize() != 2 && pkt
->getSize() !=4)
422 panic("Bad IDE read size: %d\n", pkt
->getSize());
424 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
427 pkt
->makeAtomicResponse();
433 switch (pkt
->getSize()) {
434 case sizeof(uint8_t):
435 pkt
->set(bmi_regs
.data
[offset
]);
437 case sizeof(uint16_t):
438 pkt
->set(*(uint16_t*)&bmi_regs
.data
[offset
]);
440 case sizeof(uint32_t):
441 pkt
->set(*(uint32_t*)&bmi_regs
.data
[offset
]);
444 panic("IDE read of BMI reg invalid size: %#x\n", pkt
->getSize());
450 disk
= getDisk(channel
);
452 if (disks
[disk
] == NULL
) {
453 pkt
->set
<uint8_t>(0);
459 switch (pkt
->getSize()) {
460 case sizeof(uint16_t):
461 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
464 case sizeof(uint32_t):
465 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
466 disks
[disk
]->read(offset
, reg_type
,
467 pkt
->getPtr
<uint8_t>() + sizeof(uint16_t));
471 panic("IDE read of data reg invalid size: %#x\n", pkt
->getSize());
475 if (pkt
->getSize() == sizeof(uint8_t)) {
476 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
478 panic("IDE read of command reg of invalid size: %#x\n", pkt
->getSize());
482 panic("IDE controller read of unknown register block type!\n");
484 if (pkt
->getSize() == 1)
485 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
486 offset
, pkt
->getSize(), (uint32_t)pkt
->get
<uint8_t>());
487 else if (pkt
->getSize() == 2)
488 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
489 offset
, pkt
->getSize(), pkt
->get
<uint16_t>());
491 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
492 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
494 pkt
->makeAtomicResponse();
499 IdeController::write(PacketPtr pkt
)
505 uint8_t oldVal
, newVal
;
507 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
510 pkt
->makeAtomicResponse();
511 DPRINTF(IdeCtrl
, "io not enabled\n");
518 pkt
->makeAtomicResponse();
523 // Bus master IDE command register
526 if (pkt
->getSize() != sizeof(uint8_t))
527 panic("Invalid BMIC write size: %x\n", pkt
->getSize());
529 // select the current disk based on DEV bit
530 disk
= getDisk(channel
);
532 oldVal
= bmi_regs
.chan
[channel
].bmic
;
533 newVal
= pkt
->get
<uint8_t>();
535 // if a DMA transfer is in progress, R/W control cannot change
537 if ((oldVal
& RWCON
) ^ (newVal
& RWCON
)) {
538 (oldVal
& RWCON
) ? newVal
|= RWCON
: newVal
&= ~RWCON
;
542 // see if the start/stop bit is being changed
543 if ((oldVal
& SSBM
) ^ (newVal
& SSBM
)) {
545 // stopping DMA transfer
546 DPRINTF(IdeCtrl
, "Stopping DMA transfer\n");
548 // clear the BMIDEA bit
549 bmi_regs
.chan
[channel
].bmis
=
550 bmi_regs
.chan
[channel
].bmis
& ~BMIDEA
;
552 if (disks
[disk
] == NULL
)
553 panic("DMA stop for disk %d which does not exist\n",
556 // inform the disk of the DMA transfer abort
557 disks
[disk
]->abortDma();
559 // starting DMA transfer
560 DPRINTF(IdeCtrl
, "Starting DMA transfer\n");
562 // set the BMIDEA bit
563 bmi_regs
.chan
[channel
].bmis
=
564 bmi_regs
.chan
[channel
].bmis
| BMIDEA
;
566 if (disks
[disk
] == NULL
)
567 panic("DMA start for disk %d which does not exist\n",
570 // inform the disk of the DMA transfer start
571 disks
[disk
]->startDma(letoh(bmi_regs
.chan
[channel
].bmidtp
));
575 // update the register value
576 bmi_regs
.chan
[channel
].bmic
= newVal
;
579 // Bus master IDE status register
582 if (pkt
->getSize() != sizeof(uint8_t))
583 panic("Invalid BMIS write size: %x\n", pkt
->getSize());
585 oldVal
= bmi_regs
.chan
[channel
].bmis
;
586 newVal
= pkt
->get
<uint8_t>();
588 // the BMIDEA bit is RO
589 newVal
|= (oldVal
& BMIDEA
);
591 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
592 if ((oldVal
& IDEINTS
) && (newVal
& IDEINTS
))
593 newVal
&= ~IDEINTS
; // clear the interrupt?
595 (oldVal
& IDEINTS
) ? newVal
|= IDEINTS
: newVal
&= ~IDEINTS
;
597 if ((oldVal
& IDEDMAE
) && (newVal
& IDEDMAE
))
600 (oldVal
& IDEDMAE
) ? newVal
|= IDEDMAE
: newVal
&= ~IDEDMAE
;
602 bmi_regs
.chan
[channel
].bmis
= newVal
;
605 // Bus master IDE descriptor table pointer register
609 if (pkt
->getSize() != sizeof(uint32_t))
610 panic("Invalid BMIDTP write size: %x\n", pkt
->getSize());
612 bmi_regs
.chan
[channel
].bmidtp
= htole(pkt
->get
<uint32_t>() & ~0x3);
617 if (pkt
->getSize() != sizeof(uint8_t) &&
618 pkt
->getSize() != sizeof(uint16_t) &&
619 pkt
->getSize() != sizeof(uint32_t))
620 panic("IDE controller write of invalid write size: %x\n",
623 // do a default copy of data into the registers
624 memcpy(&bmi_regs
.data
[offset
], pkt
->getPtr
<uint8_t>(), pkt
->getSize());
628 if (offset
== IDE_SELECT_OFFSET
) {
629 uint8_t *devBit
= &dev
[channel
];
630 *devBit
= (letoh(pkt
->get
<uint8_t>()) & IDE_SELECT_DEV_BIT
) ? 1 : 0;
634 disk
= getDisk(channel
);
636 if (disks
[disk
] == NULL
)
641 switch (pkt
->getSize()) {
642 case sizeof(uint16_t):
643 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
646 case sizeof(uint32_t):
647 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
648 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>() +
652 panic("IDE write of data reg invalid size: %#x\n", pkt
->getSize());
656 if (pkt
->getSize() == sizeof(uint8_t)) {
657 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
659 panic("IDE write of command reg of invalid size: %#x\n", pkt
->getSize());
663 panic("IDE controller write of unknown register block type!\n");
666 if (pkt
->getSize() == 1)
667 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
668 offset
, pkt
->getSize(), (uint32_t)pkt
->get
<uint8_t>());
669 else if (pkt
->getSize() == 2)
670 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
671 offset
, pkt
->getSize(), pkt
->get
<uint16_t>());
673 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
674 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
677 pkt
->makeAtomicResponse();
686 IdeController::serialize(std::ostream
&os
)
688 // Serialize the PciDev base class
689 PciDev::serialize(os
);
691 // Serialize register addresses and sizes
692 SERIALIZE_SCALAR(pri_cmd_addr
);
693 SERIALIZE_SCALAR(pri_cmd_size
);
694 SERIALIZE_SCALAR(pri_ctrl_addr
);
695 SERIALIZE_SCALAR(pri_ctrl_size
);
696 SERIALIZE_SCALAR(sec_cmd_addr
);
697 SERIALIZE_SCALAR(sec_cmd_size
);
698 SERIALIZE_SCALAR(sec_ctrl_addr
);
699 SERIALIZE_SCALAR(sec_ctrl_size
);
700 SERIALIZE_SCALAR(bmi_addr
);
701 SERIALIZE_SCALAR(bmi_size
);
703 // Serialize registers
704 SERIALIZE_ARRAY(bmi_regs
.data
,
705 sizeof(bmi_regs
.data
) / sizeof(bmi_regs
.data
[0]));
706 SERIALIZE_ARRAY(dev
, sizeof(dev
) / sizeof(dev
[0]));
707 SERIALIZE_ARRAY(config_regs
.data
,
708 sizeof(config_regs
.data
) / sizeof(config_regs
.data
[0]));
710 // Serialize internal state
711 SERIALIZE_SCALAR(io_enabled
);
712 SERIALIZE_SCALAR(bm_enabled
);
713 SERIALIZE_ARRAY(cmd_in_progress
,
714 sizeof(cmd_in_progress
) / sizeof(cmd_in_progress
[0]));
718 IdeController::unserialize(Checkpoint
*cp
, const std::string
§ion
)
720 // Unserialize the PciDev base class
721 PciDev::unserialize(cp
, section
);
723 // Unserialize register addresses and sizes
724 UNSERIALIZE_SCALAR(pri_cmd_addr
);
725 UNSERIALIZE_SCALAR(pri_cmd_size
);
726 UNSERIALIZE_SCALAR(pri_ctrl_addr
);
727 UNSERIALIZE_SCALAR(pri_ctrl_size
);
728 UNSERIALIZE_SCALAR(sec_cmd_addr
);
729 UNSERIALIZE_SCALAR(sec_cmd_size
);
730 UNSERIALIZE_SCALAR(sec_ctrl_addr
);
731 UNSERIALIZE_SCALAR(sec_ctrl_size
);
732 UNSERIALIZE_SCALAR(bmi_addr
);
733 UNSERIALIZE_SCALAR(bmi_size
);
735 // Unserialize registers
736 UNSERIALIZE_ARRAY(bmi_regs
.data
,
737 sizeof(bmi_regs
.data
) / sizeof(bmi_regs
.data
[0]));
738 UNSERIALIZE_ARRAY(dev
, sizeof(dev
) / sizeof(dev
[0]));
739 UNSERIALIZE_ARRAY(config_regs
.data
,
740 sizeof(config_regs
.data
) / sizeof(config_regs
.data
[0]));
742 // Unserialize internal state
743 UNSERIALIZE_SCALAR(io_enabled
);
744 UNSERIALIZE_SCALAR(bm_enabled
);
745 UNSERIALIZE_ARRAY(cmd_in_progress
,
746 sizeof(cmd_in_progress
) / sizeof(cmd_in_progress
[0]));
749 #ifndef DOXYGEN_SHOULD_SKIP_THIS
751 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
753 SimObjectParam
<System
*> system
;
754 SimObjectParam
<Platform
*> platform
;
755 Param
<Tick
> min_backoff_delay
;
756 Param
<Tick
> max_backoff_delay
;
757 SimObjectParam
<PciConfigData
*> configdata
;
758 Param
<uint32_t> pci_bus
;
759 Param
<uint32_t> pci_dev
;
760 Param
<uint32_t> pci_func
;
761 Param
<Tick
> pio_latency
;
762 Param
<Tick
> config_latency
;
763 SimObjectVectorParam
<IdeDisk
*> disks
;
765 END_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
767 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController
)
769 INIT_PARAM(system
, "System pointer"),
770 INIT_PARAM(platform
, "Platform pointer"),
771 INIT_PARAM(min_backoff_delay
, "Minimum delay after receving a nack packed"),
772 INIT_PARAM(max_backoff_delay
, "Maximum delay after receving a nack packed"),
773 INIT_PARAM(configdata
, "PCI Config data"),
774 INIT_PARAM(pci_bus
, "PCI bus ID"),
775 INIT_PARAM(pci_dev
, "PCI device number"),
776 INIT_PARAM(pci_func
, "PCI function code"),
777 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
778 INIT_PARAM(config_latency
, "Number of cycles for a config read or write"),
779 INIT_PARAM(disks
, "IDE disks attached to this controller")
781 END_INIT_SIM_OBJECT_PARAMS(IdeController
)
783 CREATE_SIM_OBJECT(IdeController
)
785 IdeController::Params
*params
= new IdeController::Params
;
786 params
->name
= getInstanceName();
787 params
->platform
= platform
;
788 params
->system
= system
;
789 params
->min_backoff_delay
= min_backoff_delay
;
790 params
->max_backoff_delay
= max_backoff_delay
;
791 params
->configData
= configdata
;
792 params
->busNum
= pci_bus
;
793 params
->deviceNum
= pci_dev
;
794 params
->functionNum
= pci_func
;
795 params
->pio_delay
= pio_latency
;
796 params
->config_delay
= config_latency
;
797 params
->disks
= disks
;
798 return new IdeController(params
);
801 REGISTER_SIM_OBJECT("IdeController", IdeController
)
803 #endif //DOXYGEN_SHOULD_SKIP_THIS