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