1/* 2 * Copyright (c) 2013 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2004-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Andrew Schultz 41 * Ali Saidi 42 * Miguel Serrano 43 */ 44 45#include "dev/storage/ide_ctrl.hh" 46 47#include <string> 48 49#include "cpu/intr_control.hh" 50#include "debug/IdeCtrl.hh" 51#include "dev/storage/ide_disk.hh" 52#include "mem/packet.hh" 53#include "mem/packet_access.hh" 54#include "params/IdeController.hh" 55#include "sim/byteswap.hh" 56 57// clang complains about std::set being overloaded with Packet::set if 58// we open up the entire namespace std 59using std::string; 60 61// Bus master IDE registers 62enum BMIRegOffset { 63 BMICommand = 0x0, 64 BMIStatus = 0x2, 65 BMIDescTablePtr = 0x4 66}; 67 68// PCI config space registers 69enum ConfRegOffset { 70 PrimaryTiming = 0x40, 71 SecondaryTiming = 0x42, 72 DeviceTiming = 0x44, 73 UDMAControl = 0x48, 74 UDMATiming = 0x4A, 75 IDEConfig = 0x54 76}; 77 78static const uint16_t timeRegWithDecodeEn = 0x8000; 79 80IdeController::Channel::Channel( 81 string newName, Addr _cmdSize, Addr _ctrlSize) : 82 _name(newName), 83 cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize), 84 master(NULL), slave(NULL), selected(NULL) 85{ 86 bmiRegs.reset(); 87 bmiRegs.status.dmaCap0 = 1; 88 bmiRegs.status.dmaCap1 = 1; 89} 90 91IdeController::Channel::~Channel() 92{ 93} 94 95IdeController::IdeController(Params *p) 96 : PciDevice(p), primary(name() + ".primary", BARSize[0], BARSize[1]), 97 secondary(name() + ".secondary", BARSize[2], BARSize[3]), 98 bmiAddr(0), bmiSize(BARSize[4]), 99 primaryTiming(htole(timeRegWithDecodeEn)), 100 secondaryTiming(htole(timeRegWithDecodeEn)), 101 deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0), 102 ioEnabled(false), bmEnabled(false), 103 ioShift(p->io_shift), ctrlOffset(p->ctrl_offset) 104{ 105 106 // Assign the disks to channels 107 for (int i = 0; i < params()->disks.size(); i++) { 108 if (!params()->disks[i]) 109 continue; 110 switch (i) { 111 case 0: 112 primary.master = params()->disks[0]; 113 break; 114 case 1: 115 primary.slave = params()->disks[1]; 116 break; 117 case 2: 118 secondary.master = params()->disks[2]; 119 break; 120 case 3: 121 secondary.slave = params()->disks[3]; 122 break; 123 default: 124 panic("IDE controllers support a maximum " 125 "of 4 devices attached!\n"); 126 } 127 params()->disks[i]->setController(this); 128 } 129 130 primary.select(false); 131 secondary.select(false); 132 133 if ((BARAddrs[0] & ~BAR_IO_MASK) && (!legacyIO[0] || ioShift)) { 134 primary.cmdAddr = BARAddrs[0]; primary.cmdSize = BARSize[0]; 135 primary.ctrlAddr = BARAddrs[1]; primary.ctrlSize = BARSize[1]; 136 } 137 if ((BARAddrs[2] & ~BAR_IO_MASK) && (!legacyIO[2] || ioShift)) { 138 secondary.cmdAddr = BARAddrs[2]; secondary.cmdSize = BARSize[2]; 139 secondary.ctrlAddr = BARAddrs[3]; secondary.ctrlSize = BARSize[3]; 140 } 141 142 ioEnabled = (config.command & htole(PCI_CMD_IOSE)); 143 bmEnabled = (config.command & htole(PCI_CMD_BME)); 144} 145 146bool 147IdeController::isDiskSelected(IdeDisk *diskPtr) 148{ 149 return (primary.selected == diskPtr || secondary.selected == diskPtr); 150} 151 152void 153IdeController::intrPost() 154{ 155 primary.bmiRegs.status.intStatus = 1; 156 PciDevice::intrPost(); 157} 158 159void 160IdeController::setDmaComplete(IdeDisk *disk) 161{ 162 Channel *channel; 163 if (disk == primary.master || disk == primary.slave) { 164 channel = &primary; 165 } else if (disk == secondary.master || disk == secondary.slave) { 166 channel = &secondary; 167 } else { 168 panic("Unable to find disk based on pointer %#x\n", disk); 169 } 170 171 channel->bmiRegs.command.startStop = 0; 172 channel->bmiRegs.status.active = 0; 173 channel->bmiRegs.status.intStatus = 1; 174} 175 176Tick 177IdeController::readConfig(PacketPtr pkt) 178{ 179 int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 180 if (offset < PCI_DEVICE_SPECIFIC) { 181 return PciDevice::readConfig(pkt); 182 } 183 184 switch (pkt->getSize()) { 185 case sizeof(uint8_t): 186 switch (offset) { 187 case DeviceTiming: 188 pkt->setLE<uint8_t>(deviceTiming); 189 break; 190 case UDMAControl: 191 pkt->setLE<uint8_t>(udmaControl); 192 break; 193 case PrimaryTiming + 1: 194 pkt->setLE<uint8_t>(bits(htole(primaryTiming), 15, 8)); 195 break; 196 case SecondaryTiming + 1: 197 pkt->setLE<uint8_t>(bits(htole(secondaryTiming), 15, 8)); 198 break; 199 case IDEConfig: 200 pkt->setLE<uint8_t>(bits(htole(ideConfig), 7, 0)); 201 break; 202 case IDEConfig + 1: 203 pkt->setLE<uint8_t>(bits(htole(ideConfig), 15, 8)); 204 break; 205 default: 206 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", 207 offset); 208 } 209 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset, 210 (uint32_t)pkt->getLE<uint8_t>()); 211 break; 212 case sizeof(uint16_t): 213 switch (offset) { 214 case UDMAControl: 215 pkt->setLE<uint16_t>(udmaControl); 216 break; 217 case PrimaryTiming: 218 pkt->setLE<uint16_t>(primaryTiming); 219 break; 220 case SecondaryTiming: 221 pkt->setLE<uint16_t>(secondaryTiming); 222 break; 223 case UDMATiming: 224 pkt->setLE<uint16_t>(udmaTiming); 225 break; 226 case IDEConfig: 227 pkt->setLE<uint16_t>(ideConfig); 228 break; 229 default: 230 panic("Invalid PCI configuration read for size 2 offset: %#x!\n", 231 offset); 232 } 233 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, 234 (uint32_t)pkt->getLE<uint16_t>()); 235 break; 236 case sizeof(uint32_t): 237 switch (offset) { 238 case PrimaryTiming: 239 pkt->setLE<uint32_t>(primaryTiming); 240 break; 241 case IDEConfig: 242 pkt->setLE<uint32_t>(ideConfig); 243 break; 244 default: 245 panic("No 32bit reads implemented for this device."); 246 } 247 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, 248 (uint32_t)pkt->getLE<uint32_t>()); 249 break; 250 default: 251 panic("invalid access size(?) for PCI configspace!\n"); 252 } 253 pkt->makeAtomicResponse(); 254 return configDelay; 255} 256 257 258Tick 259IdeController::writeConfig(PacketPtr pkt) 260{ 261 int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 262 if (offset < PCI_DEVICE_SPECIFIC) { 263 PciDevice::writeConfig(pkt); 264 } else { 265 switch (pkt->getSize()) { 266 case sizeof(uint8_t): 267 switch (offset) { 268 case DeviceTiming: 269 deviceTiming = pkt->getLE<uint8_t>(); 270 break; 271 case UDMAControl: 272 udmaControl = pkt->getLE<uint8_t>(); 273 break; 274 case IDEConfig: 275 replaceBits(ideConfig, 7, 0, pkt->getLE<uint8_t>()); 276 break; 277 case IDEConfig + 1: 278 replaceBits(ideConfig, 15, 8, pkt->getLE<uint8_t>()); 279 break; 280 default: 281 panic("Invalid PCI configuration write " 282 "for size 1 offset: %#x!\n", offset); 283 } 284 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", 285 offset, (uint32_t)pkt->getLE<uint8_t>()); 286 break; 287 case sizeof(uint16_t): 288 switch (offset) { 289 case UDMAControl: 290 udmaControl = pkt->getLE<uint16_t>(); 291 break; 292 case PrimaryTiming: 293 primaryTiming = pkt->getLE<uint16_t>(); 294 break; 295 case SecondaryTiming: 296 secondaryTiming = pkt->getLE<uint16_t>(); 297 break; 298 case UDMATiming: 299 udmaTiming = pkt->getLE<uint16_t>(); 300 break; 301 case IDEConfig: 302 ideConfig = pkt->getLE<uint16_t>(); 303 break; 304 default: 305 panic("Invalid PCI configuration write " 306 "for size 2 offset: %#x!\n", 307 offset); 308 } 309 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", 310 offset, (uint32_t)pkt->getLE<uint16_t>()); 311 break; 312 case sizeof(uint32_t): 313 switch (offset) { 314 case PrimaryTiming: 315 primaryTiming = pkt->getLE<uint32_t>(); 316 break; 317 case IDEConfig: 318 ideConfig = pkt->getLE<uint32_t>(); 319 break; 320 default: 321 panic("Write of unimplemented PCI config. register: %x\n", offset); 322 } 323 break; 324 default: 325 panic("invalid access size(?) for PCI configspace!\n"); 326 } 327 pkt->makeAtomicResponse(); 328 } 329 330 /* Trap command register writes and enable IO/BM as appropriate as well as 331 * BARs. */ 332 switch(offset) { 333 case PCI0_BASE_ADDR0: 334 if (BARAddrs[0] != 0) 335 primary.cmdAddr = BARAddrs[0]; 336 break; 337 338 case PCI0_BASE_ADDR1: 339 if (BARAddrs[1] != 0) 340 primary.ctrlAddr = BARAddrs[1]; 341 break; 342 343 case PCI0_BASE_ADDR2: 344 if (BARAddrs[2] != 0) 345 secondary.cmdAddr = BARAddrs[2]; 346 break; 347 348 case PCI0_BASE_ADDR3: 349 if (BARAddrs[3] != 0) 350 secondary.ctrlAddr = BARAddrs[3]; 351 break; 352 353 case PCI0_BASE_ADDR4: 354 if (BARAddrs[4] != 0) 355 bmiAddr = BARAddrs[4]; 356 break; 357 358 case PCI_COMMAND: 359 DPRINTF(IdeCtrl, "Writing to PCI Command val: %#x\n", config.command); 360 ioEnabled = (config.command & htole(PCI_CMD_IOSE)); 361 bmEnabled = (config.command & htole(PCI_CMD_BME)); 362 break; 363 } 364 return configDelay; 365} 366 367void 368IdeController::Channel::accessCommand(Addr offset, 369 int size, uint8_t *data, bool read) 370{ 371 const Addr SelectOffset = 6; 372 const uint8_t SelectDevBit = 0x10; 373 374 if (!read && offset == SelectOffset) 375 select(*data & SelectDevBit); 376 377 if (selected == NULL) { 378 assert(size == sizeof(uint8_t)); 379 *data = 0; 380 } else if (read) { 381 selected->readCommand(offset, size, data); 382 } else { 383 selected->writeCommand(offset, size, data); 384 } 385} 386 387void 388IdeController::Channel::accessControl(Addr offset, 389 int size, uint8_t *data, bool read) 390{ 391 if (selected == NULL) { 392 assert(size == sizeof(uint8_t)); 393 *data = 0; 394 } else if (read) { 395 selected->readControl(offset, size, data); 396 } else { 397 selected->writeControl(offset, size, data); 398 } 399} 400 401void 402IdeController::Channel::accessBMI(Addr offset, 403 int size, uint8_t *data, bool read) 404{ 405 assert(offset + size <= sizeof(BMIRegs)); 406 if (read) { 407 memcpy(data, (uint8_t *)&bmiRegs + offset, size); 408 } else { 409 switch (offset) { 410 case BMICommand: 411 { 412 if (size != sizeof(uint8_t)) 413 panic("Invalid BMIC write size: %x\n", size); 414 415 BMICommandReg oldVal = bmiRegs.command; 416 BMICommandReg newVal = *data; 417 418 // if a DMA transfer is in progress, R/W control cannot change 419 if (oldVal.startStop && oldVal.rw != newVal.rw) 420 oldVal.rw = newVal.rw; 421 422 if (oldVal.startStop != newVal.startStop) { 423 if (selected == NULL) 424 panic("DMA start for disk which does not exist\n"); 425 426 if (oldVal.startStop) { 427 DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 428 bmiRegs.status.active = 0; 429 430 selected->abortDma(); 431 } else { 432 DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 433 bmiRegs.status.active = 1; 434 435 selected->startDma(letoh(bmiRegs.bmidtp)); 436 } 437 } 438 439 bmiRegs.command = newVal; 440 } 441 break; 442 case BMIStatus: 443 { 444 if (size != sizeof(uint8_t)) 445 panic("Invalid BMIS write size: %x\n", size); 446 447 BMIStatusReg oldVal = bmiRegs.status; 448 BMIStatusReg newVal = *data; 449 450 // the BMIDEA bit is read only 451 newVal.active = oldVal.active; 452 453 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 454 if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) { 455 newVal.intStatus = 0; // clear the interrupt? 456 } else { 457 // Assigning two bitunion fields to each other does not 458 // work as intended, so we need to use this temporary variable 459 // to get around the bug. 460 uint8_t tmp = oldVal.intStatus; 461 newVal.intStatus = tmp; 462 } 463 if ((oldVal.dmaError == 1) && (newVal.dmaError == 1)) { 464 newVal.dmaError = 0; 465 } else { 466 uint8_t tmp = oldVal.dmaError; 467 newVal.dmaError = tmp; 468 } 469 470 bmiRegs.status = newVal; 471 } 472 break; 473 case BMIDescTablePtr: 474 if (size != sizeof(uint32_t)) 475 panic("Invalid BMIDTP write size: %x\n", size); 476 bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3); 477 break; 478 default: 479 if (size != sizeof(uint8_t) && size != sizeof(uint16_t) && 480 size != sizeof(uint32_t)) 481 panic("IDE controller write of invalid write size: %x\n", size); 482 memcpy((uint8_t *)&bmiRegs + offset, data, size); 483 } 484 } 485} 486 487void 488IdeController::dispatchAccess(PacketPtr pkt, bool read) 489{ 490 if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) 491 panic("Bad IDE read size: %d\n", pkt->getSize()); 492 493 if (!ioEnabled) { 494 pkt->makeAtomicResponse(); 495 DPRINTF(IdeCtrl, "io not enabled\n"); 496 return; 497 } 498 499 Addr addr = pkt->getAddr(); 500 int size = pkt->getSize(); 501 uint8_t *dataPtr = pkt->getPtr<uint8_t>(); 502 503 if (addr >= primary.cmdAddr && 504 addr < (primary.cmdAddr + primary.cmdSize)) { 505 addr -= primary.cmdAddr; 506 // linux may have shifted the address by ioShift, 507 // here we shift it back, similarly for ctrlOffset. 508 addr >>= ioShift; 509 primary.accessCommand(addr, size, dataPtr, read); 510 } else if (addr >= primary.ctrlAddr && 511 addr < (primary.ctrlAddr + primary.ctrlSize)) { 512 addr -= primary.ctrlAddr; 513 addr += ctrlOffset; 514 primary.accessControl(addr, size, dataPtr, read); 515 } else if (addr >= secondary.cmdAddr && 516 addr < (secondary.cmdAddr + secondary.cmdSize)) { 517 addr -= secondary.cmdAddr; 518 secondary.accessCommand(addr, size, dataPtr, read); 519 } else if (addr >= secondary.ctrlAddr && 520 addr < (secondary.ctrlAddr + secondary.ctrlSize)) { 521 addr -= secondary.ctrlAddr; 522 secondary.accessControl(addr, size, dataPtr, read); 523 } else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) { 524 if (!read && !bmEnabled) 525 return; 526 addr -= bmiAddr; 527 if (addr < sizeof(Channel::BMIRegs)) { 528 primary.accessBMI(addr, size, dataPtr, read); 529 } else { 530 addr -= sizeof(Channel::BMIRegs); 531 secondary.accessBMI(addr, size, dataPtr, read); 532 } 533 } else { 534 panic("IDE controller access to invalid address: %#x\n", addr); 535 } 536 537#ifndef NDEBUG 538 uint32_t data; 539 if (pkt->getSize() == 1) 540 data = pkt->getLE<uint8_t>(); 541 else if (pkt->getSize() == 2) 542 data = pkt->getLE<uint16_t>(); 543 else 544 data = pkt->getLE<uint32_t>(); 545 DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n", 546 read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data); 547#endif 548 549 pkt->makeAtomicResponse(); 550} 551 552Tick 553IdeController::read(PacketPtr pkt) 554{ 555 dispatchAccess(pkt, true); 556 return pioDelay; 557} 558 559Tick 560IdeController::write(PacketPtr pkt) 561{ 562 dispatchAccess(pkt, false); 563 return pioDelay; 564} 565 566void 567IdeController::serialize(CheckpointOut &cp) const 568{ 569 // Serialize the PciDevice base class 570 PciDevice::serialize(cp); 571 572 // Serialize channels 573 primary.serialize("primary", cp); 574 secondary.serialize("secondary", cp); 575 576 // Serialize config registers 577 SERIALIZE_SCALAR(primaryTiming); 578 SERIALIZE_SCALAR(secondaryTiming); 579 SERIALIZE_SCALAR(deviceTiming); 580 SERIALIZE_SCALAR(udmaControl); 581 SERIALIZE_SCALAR(udmaTiming); 582 SERIALIZE_SCALAR(ideConfig); 583 584 // Serialize internal state 585 SERIALIZE_SCALAR(ioEnabled); 586 SERIALIZE_SCALAR(bmEnabled); 587 SERIALIZE_SCALAR(bmiAddr); 588 SERIALIZE_SCALAR(bmiSize); 589} 590 591void 592IdeController::Channel::serialize(const std::string &base, 593 CheckpointOut &cp) const 594{ 595 paramOut(cp, base + ".cmdAddr", cmdAddr); 596 paramOut(cp, base + ".cmdSize", cmdSize); 597 paramOut(cp, base + ".ctrlAddr", ctrlAddr); 598 paramOut(cp, base + ".ctrlSize", ctrlSize); 599 uint8_t command = bmiRegs.command; 600 paramOut(cp, base + ".bmiRegs.command", command); 601 paramOut(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0); 602 uint8_t status = bmiRegs.status; 603 paramOut(cp, base + ".bmiRegs.status", status); 604 paramOut(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1); 605 paramOut(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp); 606 paramOut(cp, base + ".selectBit", selectBit); 607} 608 609void 610IdeController::unserialize(CheckpointIn &cp) 611{ 612 // Unserialize the PciDevice base class 613 PciDevice::unserialize(cp); 614 615 // Unserialize channels 616 primary.unserialize("primary", cp); 617 secondary.unserialize("secondary", cp); 618 619 // Unserialize config registers 620 UNSERIALIZE_SCALAR(primaryTiming); 621 UNSERIALIZE_SCALAR(secondaryTiming); 622 UNSERIALIZE_SCALAR(deviceTiming); 623 UNSERIALIZE_SCALAR(udmaControl); 624 UNSERIALIZE_SCALAR(udmaTiming); 625 UNSERIALIZE_SCALAR(ideConfig); 626 627 // Unserialize internal state 628 UNSERIALIZE_SCALAR(ioEnabled); 629 UNSERIALIZE_SCALAR(bmEnabled); 630 UNSERIALIZE_SCALAR(bmiAddr); 631 UNSERIALIZE_SCALAR(bmiSize); 632} 633 634void 635IdeController::Channel::unserialize(const std::string &base, CheckpointIn &cp) 636{ 637 paramIn(cp, base + ".cmdAddr", cmdAddr); 638 paramIn(cp, base + ".cmdSize", cmdSize); 639 paramIn(cp, base + ".ctrlAddr", ctrlAddr); 640 paramIn(cp, base + ".ctrlSize", ctrlSize); 641 uint8_t command; 642 paramIn(cp, base +".bmiRegs.command", command); 643 bmiRegs.command = command; 644 paramIn(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0); 645 uint8_t status; 646 paramIn(cp, base + ".bmiRegs.status", status); 647 bmiRegs.status = status; 648 paramIn(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1); 649 paramIn(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp); 650 paramIn(cp, base + ".selectBit", selectBit); 651 select(selectBit); 652} 653 654IdeController * 655IdeControllerParams::create() 656{ 657 return new IdeController(this); 658} 659