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(int offset
, uint8_t *data
)
233 if (offset
< PCI_DEVICE_SPECIFIC
) {
234 PciDev::readConfig(offset
, data
);
235 } else if (offset
>= IDE_CTRL_CONF_START
&&
236 (offset
+ 1) <= IDE_CTRL_CONF_END
) {
239 case IDE_CTRL_CONF_DEV_TIMING
:
240 *data
= config_regs
.sidetim
;
242 case IDE_CTRL_CONF_UDMA_CNTRL
:
243 *data
= config_regs
.udmactl
;
245 case IDE_CTRL_CONF_PRIM_TIMING
+1:
246 *data
= htole(config_regs
.idetim0
) >> 8;
248 case IDE_CTRL_CONF_SEC_TIMING
+1:
249 *data
= htole(config_regs
.idetim1
) >> 8;
251 case IDE_CTRL_CONF_IDE_CONFIG
:
252 *data
= htole(config_regs
.ideconfig
) & 0xFF;
254 case IDE_CTRL_CONF_IDE_CONFIG
+1:
255 *data
= htole(config_regs
.ideconfig
) >> 8;
258 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
263 panic("Read of unimplemented PCI config. register: %x\n", offset
);
265 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 1 data: %#x\n",
266 offset
, (uint32_t)*data
);
270 IdeController::readConfig(int offset
, uint16_t *data
)
272 if (offset
< PCI_DEVICE_SPECIFIC
) {
273 PciDev::readConfig(offset
, data
);
274 } else if (offset
>= IDE_CTRL_CONF_START
&&
275 (offset
+ 2) <= IDE_CTRL_CONF_END
) {
278 case IDE_CTRL_CONF_PRIM_TIMING
:
279 *data
= config_regs
.idetim0
;
281 case IDE_CTRL_CONF_SEC_TIMING
:
282 *data
= config_regs
.idetim1
;
284 case IDE_CTRL_CONF_UDMA_TIMING
:
285 *data
= config_regs
.udmatim
;
287 case IDE_CTRL_CONF_IDE_CONFIG
:
288 *data
= config_regs
.ideconfig
;
291 panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
296 panic("Read of unimplemented PCI config. register: %x\n", offset
);
298 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 2 data: %#x\n", offset
, *data
);
302 IdeController::readConfig(int offset
, uint32_t *data
)
304 if (offset
< PCI_DEVICE_SPECIFIC
) {
305 PciDev::readConfig(offset
, data
);
307 panic("Read of unimplemented PCI config. register: %x\n", offset
);
309 DPRINTF(IdeCtrl
, "PCI read offset: %#x size: 4 data: %#x\n", offset
, *data
);
312 IdeController::writeConfig(int offset
, const uint8_t data
)
314 if (offset
< PCI_DEVICE_SPECIFIC
) {
315 PciDev::writeConfig(offset
, data
);
316 } else if (offset
>= IDE_CTRL_CONF_START
&&
317 (offset
+ 1) <= IDE_CTRL_CONF_END
) {
320 case IDE_CTRL_CONF_DEV_TIMING
:
321 config_regs
.sidetim
= data
;
323 case IDE_CTRL_CONF_UDMA_CNTRL
:
324 config_regs
.udmactl
= data
;
326 case IDE_CTRL_CONF_IDE_CONFIG
:
327 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0xFF00) | (data
);
329 case IDE_CTRL_CONF_IDE_CONFIG
+1:
330 config_regs
.ideconfig
= (config_regs
.ideconfig
& 0x00FF) | data
<< 8;
333 panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
338 panic("Read of unimplemented PCI config. register: %x\n", offset
);
340 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 1 data: %#x\n",
341 offset
, (uint32_t)data
);
345 IdeController::writeConfig(int offset
, const uint16_t data
)
347 if (offset
< PCI_DEVICE_SPECIFIC
) {
348 PciDev::writeConfig(offset
, data
);
349 } else if (offset
>= IDE_CTRL_CONF_START
&&
350 (offset
+ 2) <= IDE_CTRL_CONF_END
) {
353 case IDE_CTRL_CONF_PRIM_TIMING
:
354 config_regs
.idetim0
= data
;
356 case IDE_CTRL_CONF_SEC_TIMING
:
357 config_regs
.idetim1
= data
;
359 case IDE_CTRL_CONF_UDMA_TIMING
:
360 config_regs
.udmatim
= data
;
362 case IDE_CTRL_CONF_IDE_CONFIG
:
363 config_regs
.ideconfig
= data
;
366 panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
371 panic("Write of unimplemented PCI config. register: %x\n", offset
);
373 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 2 data: %#x\n", offset
, data
);
375 /* Trap command register writes and enable IO/BM as appropriate. */
376 if (offset
== PCI_COMMAND
) {
377 if (letoh(config
.command
) & PCI_CMD_IOSE
)
382 if (letoh(config
.command
) & PCI_CMD_BME
)
391 IdeController::writeConfig(int offset
, const uint32_t data
)
393 if (offset
< PCI_DEVICE_SPECIFIC
) {
394 PciDev::writeConfig(offset
, data
);
396 panic("Read of unimplemented PCI config. register: %x\n", offset
);
399 DPRINTF(IdeCtrl
, "PCI write offset: %#x size: 4 data: %#x\n", offset
, data
);
402 case PCI0_BASE_ADDR0
:
403 if (BARAddrs
[0] != 0)
404 pri_cmd_addr
= BARAddrs
[0];
407 case PCI0_BASE_ADDR1
:
408 if (BARAddrs
[1] != 0)
409 pri_ctrl_addr
= BARAddrs
[1];
412 case PCI0_BASE_ADDR2
:
413 if (BARAddrs
[2] != 0)
414 sec_cmd_addr
= BARAddrs
[2];
417 case PCI0_BASE_ADDR3
:
418 if (BARAddrs
[3] != 0)
419 sec_ctrl_addr
= BARAddrs
[3];
422 case PCI0_BASE_ADDR4
:
423 if (BARAddrs
[4] != 0)
424 bmi_addr
= BARAddrs
[4];
430 IdeController::read(Packet
*pkt
)
438 if (pkt
->getSize() != 1 && pkt
->getSize() != 2 && pkt
->getSize() !=4)
439 panic("Bad IDE read size: %d\n", pkt
->getSize());
441 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
444 pkt
->result
= Packet::Success
;
450 switch (pkt
->getSize()) {
451 case sizeof(uint8_t):
452 pkt
->set(bmi_regs
.data
[offset
]);
454 case sizeof(uint16_t):
455 pkt
->set(*(uint16_t*)&bmi_regs
.data
[offset
]);
457 case sizeof(uint32_t):
458 pkt
->set(*(uint32_t*)&bmi_regs
.data
[offset
]);
461 panic("IDE read of BMI reg invalid size: %#x\n", pkt
->getSize());
467 disk
= getDisk(channel
);
469 if (disks
[disk
] == NULL
) {
470 pkt
->set
<uint8_t>(0);
476 switch (pkt
->getSize()) {
477 case sizeof(uint16_t):
478 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
481 case sizeof(uint32_t):
482 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
483 disks
[disk
]->read(offset
, reg_type
,
484 pkt
->getPtr
<uint8_t>() + sizeof(uint16_t));
488 panic("IDE read of data reg invalid size: %#x\n", pkt
->getSize());
492 if (pkt
->getSize() == sizeof(uint8_t)) {
493 disks
[disk
]->read(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
495 panic("IDE read of command reg of invalid size: %#x\n", pkt
->getSize());
499 panic("IDE controller read of unknown register block type!\n");
501 if (pkt
->getSize() == 1)
502 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
503 offset
, pkt
->getSize(), (uint32_t)pkt
->get
<uint8_t>());
504 else if (pkt
->getSize() == 2)
505 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
506 offset
, pkt
->getSize(), pkt
->get
<uint16_t>());
508 DPRINTF(IdeCtrl
, "read from offset: %#x size: %#x data: %#x\n",
509 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
511 pkt
->result
= Packet::Success
;
516 IdeController::write(Packet
*pkt
)
522 uint8_t oldVal
, newVal
;
524 parseAddr(pkt
->getAddr(), offset
, channel
, reg_type
);
527 pkt
->result
= Packet::Success
;
528 DPRINTF(IdeCtrl
, "io not enabled\n");
535 pkt
->result
= Packet::Success
;
540 // Bus master IDE command register
543 if (pkt
->getSize() != sizeof(uint8_t))
544 panic("Invalid BMIC write size: %x\n", pkt
->getSize());
546 // select the current disk based on DEV bit
547 disk
= getDisk(channel
);
549 oldVal
= bmi_regs
.chan
[channel
].bmic
;
550 newVal
= pkt
->get
<uint8_t>();
552 // if a DMA transfer is in progress, R/W control cannot change
554 if ((oldVal
& RWCON
) ^ (newVal
& RWCON
)) {
555 (oldVal
& RWCON
) ? newVal
|= RWCON
: newVal
&= ~RWCON
;
559 // see if the start/stop bit is being changed
560 if ((oldVal
& SSBM
) ^ (newVal
& SSBM
)) {
562 // stopping DMA transfer
563 DPRINTF(IdeCtrl
, "Stopping DMA transfer\n");
565 // clear the BMIDEA bit
566 bmi_regs
.chan
[channel
].bmis
=
567 bmi_regs
.chan
[channel
].bmis
& ~BMIDEA
;
569 if (disks
[disk
] == NULL
)
570 panic("DMA stop for disk %d which does not exist\n",
573 // inform the disk of the DMA transfer abort
574 disks
[disk
]->abortDma();
576 // starting DMA transfer
577 DPRINTF(IdeCtrl
, "Starting DMA transfer\n");
579 // set the BMIDEA bit
580 bmi_regs
.chan
[channel
].bmis
=
581 bmi_regs
.chan
[channel
].bmis
| BMIDEA
;
583 if (disks
[disk
] == NULL
)
584 panic("DMA start for disk %d which does not exist\n",
587 // inform the disk of the DMA transfer start
588 disks
[disk
]->startDma(letoh(bmi_regs
.chan
[channel
].bmidtp
));
592 // update the register value
593 bmi_regs
.chan
[channel
].bmic
= newVal
;
596 // Bus master IDE status register
599 if (pkt
->getSize() != sizeof(uint8_t))
600 panic("Invalid BMIS write size: %x\n", pkt
->getSize());
602 oldVal
= bmi_regs
.chan
[channel
].bmis
;
603 newVal
= pkt
->get
<uint8_t>();
605 // the BMIDEA bit is RO
606 newVal
|= (oldVal
& BMIDEA
);
608 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
609 if ((oldVal
& IDEINTS
) && (newVal
& IDEINTS
))
610 newVal
&= ~IDEINTS
; // clear the interrupt?
612 (oldVal
& IDEINTS
) ? newVal
|= IDEINTS
: newVal
&= ~IDEINTS
;
614 if ((oldVal
& IDEDMAE
) && (newVal
& IDEDMAE
))
617 (oldVal
& IDEDMAE
) ? newVal
|= IDEDMAE
: newVal
&= ~IDEDMAE
;
619 bmi_regs
.chan
[channel
].bmis
= newVal
;
622 // Bus master IDE descriptor table pointer register
626 if (pkt
->getSize() != sizeof(uint32_t))
627 panic("Invalid BMIDTP write size: %x\n", pkt
->getSize());
629 bmi_regs
.chan
[channel
].bmidtp
= htole(pkt
->get
<uint32_t>() & ~0x3);
634 if (pkt
->getSize() != sizeof(uint8_t) &&
635 pkt
->getSize() != sizeof(uint16_t) &&
636 pkt
->getSize() != sizeof(uint32_t))
637 panic("IDE controller write of invalid write size: %x\n",
640 // do a default copy of data into the registers
641 memcpy(&bmi_regs
.data
[offset
], pkt
->getPtr
<uint8_t>(), pkt
->getSize());
645 if (offset
== IDE_SELECT_OFFSET
) {
646 uint8_t *devBit
= &dev
[channel
];
647 *devBit
= (letoh(pkt
->get
<uint8_t>()) & IDE_SELECT_DEV_BIT
) ? 1 : 0;
651 disk
= getDisk(channel
);
653 if (disks
[disk
] == NULL
)
658 switch (pkt
->getSize()) {
659 case sizeof(uint16_t):
660 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
663 case sizeof(uint32_t):
664 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
665 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>() +
669 panic("IDE write of data reg invalid size: %#x\n", pkt
->getSize());
673 if (pkt
->getSize() == sizeof(uint8_t)) {
674 disks
[disk
]->write(offset
, reg_type
, pkt
->getPtr
<uint8_t>());
676 panic("IDE write of command reg of invalid size: %#x\n", pkt
->getSize());
680 panic("IDE controller write of unknown register block type!\n");
683 if (pkt
->getSize() == 1)
684 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
685 offset
, pkt
->getSize(), (uint32_t)pkt
->get
<uint8_t>());
686 else if (pkt
->getSize() == 2)
687 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
688 offset
, pkt
->getSize(), pkt
->get
<uint16_t>());
690 DPRINTF(IdeCtrl
, "write to offset: %#x size: %#x data: %#x\n",
691 offset
, pkt
->getSize(), pkt
->get
<uint32_t>());
694 pkt
->result
= Packet::Success
;
703 IdeController::serialize(std::ostream
&os
)
705 // Serialize the PciDev base class
706 PciDev::serialize(os
);
708 // Serialize register addresses and sizes
709 SERIALIZE_SCALAR(pri_cmd_addr
);
710 SERIALIZE_SCALAR(pri_cmd_size
);
711 SERIALIZE_SCALAR(pri_ctrl_addr
);
712 SERIALIZE_SCALAR(pri_ctrl_size
);
713 SERIALIZE_SCALAR(sec_cmd_addr
);
714 SERIALIZE_SCALAR(sec_cmd_size
);
715 SERIALIZE_SCALAR(sec_ctrl_addr
);
716 SERIALIZE_SCALAR(sec_ctrl_size
);
717 SERIALIZE_SCALAR(bmi_addr
);
718 SERIALIZE_SCALAR(bmi_size
);
720 // Serialize registers
721 SERIALIZE_ARRAY(bmi_regs
.data
,
722 sizeof(bmi_regs
.data
) / sizeof(bmi_regs
.data
[0]));
723 SERIALIZE_ARRAY(dev
, sizeof(dev
) / sizeof(dev
[0]));
724 SERIALIZE_ARRAY(config_regs
.data
,
725 sizeof(config_regs
.data
) / sizeof(config_regs
.data
[0]));
727 // Serialize internal state
728 SERIALIZE_SCALAR(io_enabled
);
729 SERIALIZE_SCALAR(bm_enabled
);
730 SERIALIZE_ARRAY(cmd_in_progress
,
731 sizeof(cmd_in_progress
) / sizeof(cmd_in_progress
[0]));
735 IdeController::unserialize(Checkpoint
*cp
, const std::string
§ion
)
737 // Unserialize the PciDev base class
738 PciDev::unserialize(cp
, section
);
740 // Unserialize register addresses and sizes
741 UNSERIALIZE_SCALAR(pri_cmd_addr
);
742 UNSERIALIZE_SCALAR(pri_cmd_size
);
743 UNSERIALIZE_SCALAR(pri_ctrl_addr
);
744 UNSERIALIZE_SCALAR(pri_ctrl_size
);
745 UNSERIALIZE_SCALAR(sec_cmd_addr
);
746 UNSERIALIZE_SCALAR(sec_cmd_size
);
747 UNSERIALIZE_SCALAR(sec_ctrl_addr
);
748 UNSERIALIZE_SCALAR(sec_ctrl_size
);
749 UNSERIALIZE_SCALAR(bmi_addr
);
750 UNSERIALIZE_SCALAR(bmi_size
);
752 // Unserialize registers
753 UNSERIALIZE_ARRAY(bmi_regs
.data
,
754 sizeof(bmi_regs
.data
) / sizeof(bmi_regs
.data
[0]));
755 UNSERIALIZE_ARRAY(dev
, sizeof(dev
) / sizeof(dev
[0]));
756 UNSERIALIZE_ARRAY(config_regs
.data
,
757 sizeof(config_regs
.data
) / sizeof(config_regs
.data
[0]));
759 // Unserialize internal state
760 UNSERIALIZE_SCALAR(io_enabled
);
761 UNSERIALIZE_SCALAR(bm_enabled
);
762 UNSERIALIZE_ARRAY(cmd_in_progress
,
763 sizeof(cmd_in_progress
) / sizeof(cmd_in_progress
[0]));
764 pioPort
->sendStatusChange(Port::RangeChange
);
767 #ifndef DOXYGEN_SHOULD_SKIP_THIS
769 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
771 SimObjectParam
<System
*> system
;
772 SimObjectParam
<Platform
*> platform
;
773 SimObjectParam
<PciConfigAll
*> configspace
;
774 SimObjectParam
<PciConfigData
*> configdata
;
775 Param
<uint32_t> pci_bus
;
776 Param
<uint32_t> pci_dev
;
777 Param
<uint32_t> pci_func
;
778 Param
<Tick
> pio_latency
;
779 SimObjectVectorParam
<IdeDisk
*> disks
;
781 END_DECLARE_SIM_OBJECT_PARAMS(IdeController
)
783 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController
)
785 INIT_PARAM(system
, "System pointer"),
786 INIT_PARAM(platform
, "Platform pointer"),
787 INIT_PARAM(configspace
, "PCI Configspace"),
788 INIT_PARAM(configdata
, "PCI Config data"),
789 INIT_PARAM(pci_bus
, "PCI bus ID"),
790 INIT_PARAM(pci_dev
, "PCI device number"),
791 INIT_PARAM(pci_func
, "PCI function code"),
792 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
793 INIT_PARAM(disks
, "IDE disks attached to this controller")
795 END_INIT_SIM_OBJECT_PARAMS(IdeController
)
797 CREATE_SIM_OBJECT(IdeController
)
799 IdeController::Params
*params
= new IdeController::Params
;
800 params
->name
= getInstanceName();
801 params
->platform
= platform
;
802 params
->system
= system
;
803 params
->configSpace
= configspace
;
804 params
->configData
= configdata
;
805 params
->busNum
= pci_bus
;
806 params
->deviceNum
= pci_dev
;
807 params
->functionNum
= pci_func
;
808 params
->pio_delay
= pio_latency
;
809 params
->disks
= disks
;
810 return new IdeController(params
);
813 REGISTER_SIM_OBJECT("IdeController", IdeController
)
815 #endif //DOXYGEN_SHOULD_SKIP_THIS