ide_ctrl.cc revision 2665
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 * Authors: Andrew Schultz 29 * Ali Saidi 30 * Miguel Serrano 31 */ 32 33#include <cstddef> 34#include <cstdlib> 35#include <string> 36#include <vector> 37 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" 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.data, 0, sizeof(bmi_regs)); 79 memset(config_regs.data, 0, sizeof(config_regs.data)); 80 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; 87 88 // reset all internal variables 89 io_enabled = false; 90 bm_enabled = false; 91 memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); 92 93 // setup the disks attached to controller 94 memset(disks, 0, sizeof(disks)); 95 dev[0] = 0; 96 dev[1] = 0; 97 98 if (params()->disks.size() > 3) 99 panic("IDE controllers support a maximum of 4 devices attached!\n"); 100 101 for (int i = 0; i < params()->disks.size(); i++) { 102 disks[i] = params()->disks[i]; 103 disks[i]->setController(this); 104 } 105} 106 107IdeController::~IdeController() 108{ 109 for (int i = 0; i < 4; i++) 110 if (disks[i]) 111 delete disks[i]; 112} 113 114//// 115// Utility functions 116/// 117 118void 119IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, 120 IdeRegType ®_type) 121{ 122 offset = addr; 123 124 if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) { 125 offset -= pri_cmd_addr; 126 reg_type = COMMAND_BLOCK; 127 channel = PRIMARY; 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; 132 channel = PRIMARY; 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; 137 channel = SECONDARY; 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; 142 channel = SECONDARY; 143 } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) { 144 offset -= bmi_addr; 145 reg_type = BMI_BLOCK; 146 channel = (offset < BMIC1) ? PRIMARY : SECONDARY; 147 } else { 148 panic("IDE controller access to invalid address: %#x\n", addr); 149 } 150} 151 152int 153IdeController::getDisk(IdeChannel channel) 154{ 155 int disk = 0; 156 uint8_t *devBit = &dev[0]; 157 158 if (channel == SECONDARY) { 159 disk += 2; 160 devBit = &dev[1]; 161 } 162 163 disk += *devBit; 164 165 assert(*devBit == 0 || *devBit == 1); 166 167 return disk; 168} 169 170int 171IdeController::getDisk(IdeDisk *diskPtr) 172{ 173 for (int i = 0; i < 4; i++) { 174 if ((long)diskPtr == (long)disks[i]) 175 return i; 176 } 177 return -1; 178} 179 180bool 181IdeController::isDiskSelected(IdeDisk *diskPtr) 182{ 183 for (int i = 0; i < 4; i++) { 184 if ((long)diskPtr == (long)disks[i]) { 185 // is disk is on primary or secondary channel 186 int channel = i/2; 187 // is disk the master or slave 188 int devID = i%2; 189 190 return (dev[channel] == devID); 191 } 192 } 193 panic("Unable to find disk by pointer!!\n"); 194} 195 196//// 197// Command completion 198//// 199 200void 201IdeController::setDmaComplete(IdeDisk *disk) 202{ 203 int diskNum = getDisk(disk); 204 205 if (diskNum < 0) 206 panic("Unable to find disk based on pointer %#x\n", disk); 207 208 if (diskNum < 2) { 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; 215 } else { 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; 222 } 223} 224 225 226//// 227// Read and write handling 228//// 229 230void 231IdeController::readConfig(int offset, uint8_t *data) 232{ 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) { 237 238 switch (offset) { 239 case IDE_CTRL_CONF_DEV_TIMING: 240 *data = config_regs.sidetim; 241 break; 242 case IDE_CTRL_CONF_UDMA_CNTRL: 243 *data = config_regs.udmactl; 244 break; 245 case IDE_CTRL_CONF_PRIM_TIMING+1: 246 *data = htole(config_regs.idetim0) >> 8; 247 break; 248 case IDE_CTRL_CONF_SEC_TIMING+1: 249 *data = htole(config_regs.idetim1) >> 8; 250 break; 251 case IDE_CTRL_CONF_IDE_CONFIG: 252 *data = htole(config_regs.ideconfig) & 0xFF; 253 break; 254 case IDE_CTRL_CONF_IDE_CONFIG+1: 255 *data = htole(config_regs.ideconfig) >> 8; 256 break; 257 default: 258 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", 259 offset); 260 } 261 262 } else { 263 panic("Read of unimplemented PCI config. register: %x\n", offset); 264 } 265 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", 266 offset, (uint32_t)*data); 267} 268 269void 270IdeController::readConfig(int offset, uint16_t *data) 271{ 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) { 276 277 switch (offset) { 278 case IDE_CTRL_CONF_PRIM_TIMING: 279 *data = config_regs.idetim0; 280 break; 281 case IDE_CTRL_CONF_SEC_TIMING: 282 *data = config_regs.idetim1; 283 break; 284 case IDE_CTRL_CONF_UDMA_TIMING: 285 *data = config_regs.udmatim; 286 break; 287 case IDE_CTRL_CONF_IDE_CONFIG: 288 *data = config_regs.ideconfig; 289 break; 290 default: 291 panic("Invalid PCI configuration read for size 2 offset: %#x!\n", 292 offset); 293 } 294 295 } else { 296 panic("Read of unimplemented PCI config. register: %x\n", offset); 297 } 298 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data); 299} 300 301void 302IdeController::readConfig(int offset, uint32_t *data) 303{ 304 if (offset < PCI_DEVICE_SPECIFIC) { 305 PciDev::readConfig(offset, data); 306 } else { 307 panic("Read of unimplemented PCI config. register: %x\n", offset); 308 } 309 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data); 310} 311void 312IdeController::writeConfig(int offset, const uint8_t data) 313{ 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) { 318 319 switch (offset) { 320 case IDE_CTRL_CONF_DEV_TIMING: 321 config_regs.sidetim = data; 322 break; 323 case IDE_CTRL_CONF_UDMA_CNTRL: 324 config_regs.udmactl = data; 325 break; 326 case IDE_CTRL_CONF_IDE_CONFIG: 327 config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data); 328 break; 329 case IDE_CTRL_CONF_IDE_CONFIG+1: 330 config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8; 331 break; 332 default: 333 panic("Invalid PCI configuration write for size 1 offset: %#x!\n", 334 offset); 335 } 336 337 } else { 338 panic("Read of unimplemented PCI config. register: %x\n", offset); 339 } 340 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", 341 offset, (uint32_t)data); 342} 343 344void 345IdeController::writeConfig(int offset, const uint16_t data) 346{ 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) { 351 352 switch (offset) { 353 case IDE_CTRL_CONF_PRIM_TIMING: 354 config_regs.idetim0 = data; 355 break; 356 case IDE_CTRL_CONF_SEC_TIMING: 357 config_regs.idetim1 = data; 358 break; 359 case IDE_CTRL_CONF_UDMA_TIMING: 360 config_regs.udmatim = data; 361 break; 362 case IDE_CTRL_CONF_IDE_CONFIG: 363 config_regs.ideconfig = data; 364 break; 365 default: 366 panic("Invalid PCI configuration write for size 2 offset: %#x!\n", 367 offset); 368 } 369 370 } else { 371 panic("Write of unimplemented PCI config. register: %x\n", offset); 372 } 373 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data); 374 375 /* Trap command register writes and enable IO/BM as appropriate. */ 376 if (offset == PCI_COMMAND) { 377 if (letoh(config.command) & PCI_CMD_IOSE) 378 io_enabled = true; 379 else 380 io_enabled = false; 381 382 if (letoh(config.command) & PCI_CMD_BME) 383 bm_enabled = true; 384 else 385 bm_enabled = false; 386 } 387 388} 389 390void 391IdeController::writeConfig(int offset, const uint32_t data) 392{ 393 if (offset < PCI_DEVICE_SPECIFIC) { 394 PciDev::writeConfig(offset, data); 395 } else { 396 panic("Read of unimplemented PCI config. register: %x\n", offset); 397 } 398 399 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data); 400 401 switch(offset) { 402 case PCI0_BASE_ADDR0: 403 if (BARAddrs[0] != 0) 404 pri_cmd_addr = BARAddrs[0]; 405 break; 406 407 case PCI0_BASE_ADDR1: 408 if (BARAddrs[1] != 0) 409 pri_ctrl_addr = BARAddrs[1]; 410 break; 411 412 case PCI0_BASE_ADDR2: 413 if (BARAddrs[2] != 0) 414 sec_cmd_addr = BARAddrs[2]; 415 break; 416 417 case PCI0_BASE_ADDR3: 418 if (BARAddrs[3] != 0) 419 sec_ctrl_addr = BARAddrs[3]; 420 break; 421 422 case PCI0_BASE_ADDR4: 423 if (BARAddrs[4] != 0) 424 bmi_addr = BARAddrs[4]; 425 break; 426 } 427} 428 429Tick 430IdeController::read(Packet *pkt) 431{ 432 Addr offset; 433 IdeChannel channel; 434 IdeRegType reg_type; 435 int disk; 436 437 pkt->allocate(); 438 if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) 439 panic("Bad IDE read size: %d\n", pkt->getSize()); 440 441 parseAddr(pkt->getAddr(), offset, channel, reg_type); 442 443 if (!io_enabled) { 444 pkt->result = Packet::Success; 445 return pioDelay; 446 } 447 448 switch (reg_type) { 449 case BMI_BLOCK: 450 switch (pkt->getSize()) { 451 case sizeof(uint8_t): 452 pkt->set(bmi_regs.data[offset]); 453 break; 454 case sizeof(uint16_t): 455 pkt->set(*(uint16_t*)&bmi_regs.data[offset]); 456 break; 457 case sizeof(uint32_t): 458 pkt->set(*(uint32_t*)&bmi_regs.data[offset]); 459 break; 460 default: 461 panic("IDE read of BMI reg invalid size: %#x\n", pkt->getSize()); 462 } 463 break; 464 465 case COMMAND_BLOCK: 466 case CONTROL_BLOCK: 467 disk = getDisk(channel); 468 469 if (disks[disk] == NULL) { 470 pkt->set<uint8_t>(0); 471 break; 472 } 473 474 switch (offset) { 475 case DATA_OFFSET: 476 switch (pkt->getSize()) { 477 case sizeof(uint16_t): 478 disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); 479 break; 480 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)); 485 break; 486 487 default: 488 panic("IDE read of data reg invalid size: %#x\n", pkt->getSize()); 489 } 490 break; 491 default: 492 if (pkt->getSize() == sizeof(uint8_t)) { 493 disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); 494 } else 495 panic("IDE read of command reg of invalid size: %#x\n", pkt->getSize()); 496 } 497 break; 498 default: 499 panic("IDE controller read of unknown register block type!\n"); 500 } 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>()); 507 else 508 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 509 offset, pkt->getSize(), pkt->get<uint32_t>()); 510 511 pkt->result = Packet::Success; 512 return pioDelay; 513} 514 515Tick 516IdeController::write(Packet *pkt) 517{ 518 Addr offset; 519 IdeChannel channel; 520 IdeRegType reg_type; 521 int disk; 522 uint8_t oldVal, newVal; 523 524 parseAddr(pkt->getAddr(), offset, channel, reg_type); 525 526 if (!io_enabled) { 527 pkt->result = Packet::Success; 528 DPRINTF(IdeCtrl, "io not enabled\n"); 529 return pioDelay; 530 } 531 532 switch (reg_type) { 533 case BMI_BLOCK: 534 if (!bm_enabled) { 535 pkt->result = Packet::Success; 536 return pioDelay; 537 } 538 539 switch (offset) { 540 // Bus master IDE command register 541 case BMIC1: 542 case BMIC0: 543 if (pkt->getSize() != sizeof(uint8_t)) 544 panic("Invalid BMIC write size: %x\n", pkt->getSize()); 545 546 // select the current disk based on DEV bit 547 disk = getDisk(channel); 548 549 oldVal = bmi_regs.chan[channel].bmic; 550 newVal = pkt->get<uint8_t>(); 551 552 // if a DMA transfer is in progress, R/W control cannot change 553 if (oldVal & SSBM) { 554 if ((oldVal & RWCON) ^ (newVal & RWCON)) { 555 (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON; 556 } 557 } 558 559 // see if the start/stop bit is being changed 560 if ((oldVal & SSBM) ^ (newVal & SSBM)) { 561 if (oldVal & SSBM) { 562 // stopping DMA transfer 563 DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 564 565 // clear the BMIDEA bit 566 bmi_regs.chan[channel].bmis = 567 bmi_regs.chan[channel].bmis & ~BMIDEA; 568 569 if (disks[disk] == NULL) 570 panic("DMA stop for disk %d which does not exist\n", 571 disk); 572 573 // inform the disk of the DMA transfer abort 574 disks[disk]->abortDma(); 575 } else { 576 // starting DMA transfer 577 DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 578 579 // set the BMIDEA bit 580 bmi_regs.chan[channel].bmis = 581 bmi_regs.chan[channel].bmis | BMIDEA; 582 583 if (disks[disk] == NULL) 584 panic("DMA start for disk %d which does not exist\n", 585 disk); 586 587 // inform the disk of the DMA transfer start 588 disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp)); 589 } 590 } 591 592 // update the register value 593 bmi_regs.chan[channel].bmic = newVal; 594 break; 595 596 // Bus master IDE status register 597 case BMIS0: 598 case BMIS1: 599 if (pkt->getSize() != sizeof(uint8_t)) 600 panic("Invalid BMIS write size: %x\n", pkt->getSize()); 601 602 oldVal = bmi_regs.chan[channel].bmis; 603 newVal = pkt->get<uint8_t>(); 604 605 // the BMIDEA bit is RO 606 newVal |= (oldVal & BMIDEA); 607 608 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 609 if ((oldVal & IDEINTS) && (newVal & IDEINTS)) 610 newVal &= ~IDEINTS; // clear the interrupt? 611 else 612 (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS; 613 614 if ((oldVal & IDEDMAE) && (newVal & IDEDMAE)) 615 newVal &= ~IDEDMAE; 616 else 617 (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; 618 619 bmi_regs.chan[channel].bmis = newVal; 620 break; 621 622 // Bus master IDE descriptor table pointer register 623 case BMIDTP0: 624 case BMIDTP1: 625 { 626 if (pkt->getSize() != sizeof(uint32_t)) 627 panic("Invalid BMIDTP write size: %x\n", pkt->getSize()); 628 629 bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3); 630 } 631 break; 632 633 default: 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", 638 pkt->getSize()); 639 640 // do a default copy of data into the registers 641 memcpy(&bmi_regs.data[offset], pkt->getPtr<uint8_t>(), pkt->getSize()); 642 } 643 break; 644 case COMMAND_BLOCK: 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; 648 } 649 // fall-through ok! 650 case CONTROL_BLOCK: 651 disk = getDisk(channel); 652 653 if (disks[disk] == NULL) 654 break; 655 656 switch (offset) { 657 case DATA_OFFSET: 658 switch (pkt->getSize()) { 659 case sizeof(uint16_t): 660 disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); 661 break; 662 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>() + 666 sizeof(uint16_t)); 667 break; 668 default: 669 panic("IDE write of data reg invalid size: %#x\n", pkt->getSize()); 670 } 671 break; 672 default: 673 if (pkt->getSize() == sizeof(uint8_t)) { 674 disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); 675 } else 676 panic("IDE write of command reg of invalid size: %#x\n", pkt->getSize()); 677 } 678 break; 679 default: 680 panic("IDE controller write of unknown register block type!\n"); 681 } 682 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>()); 689 else 690 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 691 offset, pkt->getSize(), pkt->get<uint32_t>()); 692 693 694 pkt->result = Packet::Success; 695 return pioDelay; 696} 697 698//// 699// Serialization 700//// 701 702void 703IdeController::serialize(std::ostream &os) 704{ 705 // Serialize the PciDev base class 706 PciDev::serialize(os); 707 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); 719 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])); 726 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])); 732} 733 734void 735IdeController::unserialize(Checkpoint *cp, const std::string §ion) 736{ 737 // Unserialize the PciDev base class 738 PciDev::unserialize(cp, section); 739 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); 751 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])); 758 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); 765} 766 767#ifndef DOXYGEN_SHOULD_SKIP_THIS 768 769BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) 770 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; 780 781END_DECLARE_SIM_OBJECT_PARAMS(IdeController) 782 783BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) 784 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") 794 795END_INIT_SIM_OBJECT_PARAMS(IdeController) 796 797CREATE_SIM_OBJECT(IdeController) 798{ 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); 811} 812 813REGISTER_SIM_OBJECT("IdeController", IdeController) 814 815#endif //DOXYGEN_SHOULD_SKIP_THIS 816