ide_ctrl.cc revision 2565
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/packet.hh" 42#include "sim/builder.hh" 43#include "sim/sim_object.hh" 44#include "sim/byteswap.hh" 45 46using namespace std; 47 48//// 49// Initialization and destruction 50//// 51 52IdeController::IdeController(Params *p) 53 : PciDev(p) 54{ 55 // initialize the PIO interface addresses 56 pri_cmd_addr = 0; 57 pri_cmd_size = BARSize[0]; 58 59 pri_ctrl_addr = 0; 60 pri_ctrl_size = BARSize[1]; 61 62 sec_cmd_addr = 0; 63 sec_cmd_size = BARSize[2]; 64 65 sec_ctrl_addr = 0; 66 sec_ctrl_size = BARSize[3]; 67 68 // initialize the bus master interface (BMI) address to be configured 69 // via PCI 70 bmi_addr = 0; 71 bmi_size = BARSize[4]; 72 73 // zero out all of the registers 74 memset(bmi_regs.data, 0, sizeof(bmi_regs)); 75 memset(config_regs.data, 0, sizeof(config_regs.data)); 76 77 // setup initial values 78 // enable both channels 79 config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN); 80 config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN); 81 bmi_regs.bmis0 = DMA1CAP | DMA0CAP; 82 bmi_regs.bmis1 = DMA1CAP | DMA0CAP; 83 84 // reset all internal variables 85 io_enabled = false; 86 bm_enabled = false; 87 memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); 88 89 // setup the disks attached to controller 90 memset(disks, 0, sizeof(disks)); 91 dev[0] = 0; 92 dev[1] = 0; 93 94 if (params()->disks.size() > 3) 95 panic("IDE controllers support a maximum of 4 devices attached!\n"); 96 97 for (int i = 0; i < params()->disks.size(); i++) { 98 disks[i] = params()->disks[i]; 99 disks[i]->setController(this); 100 } 101} 102 103IdeController::~IdeController() 104{ 105 for (int i = 0; i < 4; i++) 106 if (disks[i]) 107 delete disks[i]; 108} 109 110//// 111// Utility functions 112/// 113 114void 115IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, 116 IdeRegType ®_type) 117{ 118 offset = addr; 119 120 if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) { 121 offset -= pri_cmd_addr; 122 reg_type = COMMAND_BLOCK; 123 channel = PRIMARY; 124 } else if (addr >= pri_ctrl_addr && 125 addr < (pri_ctrl_addr + pri_ctrl_size)) { 126 offset -= pri_ctrl_addr; 127 reg_type = CONTROL_BLOCK; 128 channel = PRIMARY; 129 } else if (addr >= sec_cmd_addr && 130 addr < (sec_cmd_addr + sec_cmd_size)) { 131 offset -= sec_cmd_addr; 132 reg_type = COMMAND_BLOCK; 133 channel = SECONDARY; 134 } else if (addr >= sec_ctrl_addr && 135 addr < (sec_ctrl_addr + sec_ctrl_size)) { 136 offset -= sec_ctrl_addr; 137 reg_type = CONTROL_BLOCK; 138 channel = SECONDARY; 139 } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) { 140 offset -= bmi_addr; 141 reg_type = BMI_BLOCK; 142 channel = (offset < BMIC1) ? PRIMARY : SECONDARY; 143 } else { 144 panic("IDE controller access to invalid address: %#x\n", addr); 145 } 146} 147 148int 149IdeController::getDisk(IdeChannel channel) 150{ 151 int disk = 0; 152 uint8_t *devBit = &dev[0]; 153 154 if (channel == SECONDARY) { 155 disk += 2; 156 devBit = &dev[1]; 157 } 158 159 disk += *devBit; 160 161 assert(*devBit == 0 || *devBit == 1); 162 163 return disk; 164} 165 166int 167IdeController::getDisk(IdeDisk *diskPtr) 168{ 169 for (int i = 0; i < 4; i++) { 170 if ((long)diskPtr == (long)disks[i]) 171 return i; 172 } 173 return -1; 174} 175 176bool 177IdeController::isDiskSelected(IdeDisk *diskPtr) 178{ 179 for (int i = 0; i < 4; i++) { 180 if ((long)diskPtr == (long)disks[i]) { 181 // is disk is on primary or secondary channel 182 int channel = i/2; 183 // is disk the master or slave 184 int devID = i%2; 185 186 return (dev[channel] == devID); 187 } 188 } 189 panic("Unable to find disk by pointer!!\n"); 190} 191 192//// 193// Command completion 194//// 195 196void 197IdeController::setDmaComplete(IdeDisk *disk) 198{ 199 int diskNum = getDisk(disk); 200 201 if (diskNum < 0) 202 panic("Unable to find disk based on pointer %#x\n", disk); 203 204 if (diskNum < 2) { 205 // clear the start/stop bit in the command register 206 bmi_regs.bmic0 &= ~SSBM; 207 // clear the bus master active bit in the status register 208 bmi_regs.bmis0 &= ~BMIDEA; 209 // set the interrupt bit 210 bmi_regs.bmis0 |= IDEINTS; 211 } else { 212 // clear the start/stop bit in the command register 213 bmi_regs.bmic1 &= ~SSBM; 214 // clear the bus master active bit in the status register 215 bmi_regs.bmis1 &= ~BMIDEA; 216 // set the interrupt bit 217 bmi_regs.bmis1 |= IDEINTS; 218 } 219} 220 221 222//// 223// Read and write handling 224//// 225 226void 227IdeController::readConfig(int offset, uint8_t *data) 228{ 229 if (offset < PCI_DEVICE_SPECIFIC) { 230 PciDev::readConfig(offset, data); 231 } else if (offset >= IDE_CTRL_CONF_START && 232 (offset + 1) <= IDE_CTRL_CONF_END) { 233 234 switch (offset) { 235 case IDE_CTRL_CONF_DEV_TIMING: 236 *data = config_regs.sidetim; 237 break; 238 case IDE_CTRL_CONF_UDMA_CNTRL: 239 *data = config_regs.udmactl; 240 break; 241 case IDE_CTRL_CONF_PRIM_TIMING+1: 242 *data = htole(config_regs.idetim0) >> 8; 243 break; 244 case IDE_CTRL_CONF_SEC_TIMING+1: 245 *data = htole(config_regs.idetim1) >> 8; 246 break; 247 case IDE_CTRL_CONF_IDE_CONFIG: 248 *data = htole(config_regs.ideconfig) & 0xFF; 249 break; 250 case IDE_CTRL_CONF_IDE_CONFIG+1: 251 *data = htole(config_regs.ideconfig) >> 8; 252 break; 253 default: 254 panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", 255 offset); 256 } 257 258 } else { 259 panic("Read of unimplemented PCI config. register: %x\n", offset); 260 } 261 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", 262 offset, (uint32_t)*data); 263} 264 265void 266IdeController::readConfig(int offset, uint16_t *data) 267{ 268 if (offset < PCI_DEVICE_SPECIFIC) { 269 PciDev::readConfig(offset, data); 270 } else if (offset >= IDE_CTRL_CONF_START && 271 (offset + 2) <= IDE_CTRL_CONF_END) { 272 273 switch (offset) { 274 case IDE_CTRL_CONF_PRIM_TIMING: 275 *data = config_regs.idetim0; 276 break; 277 case IDE_CTRL_CONF_SEC_TIMING: 278 *data = config_regs.idetim1; 279 break; 280 case IDE_CTRL_CONF_UDMA_TIMING: 281 *data = config_regs.udmatim; 282 break; 283 case IDE_CTRL_CONF_IDE_CONFIG: 284 *data = config_regs.ideconfig; 285 break; 286 default: 287 panic("Invalid PCI configuration read for size 2 offset: %#x!\n", 288 offset); 289 } 290 291 } else { 292 panic("Read of unimplemented PCI config. register: %x\n", offset); 293 } 294 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data); 295} 296 297void 298IdeController::readConfig(int offset, uint32_t *data) 299{ 300 if (offset < PCI_DEVICE_SPECIFIC) { 301 PciDev::readConfig(offset, data); 302 } else { 303 panic("Read of unimplemented PCI config. register: %x\n", offset); 304 } 305 DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data); 306} 307void 308IdeController::writeConfig(int offset, const uint8_t data) 309{ 310 if (offset < PCI_DEVICE_SPECIFIC) { 311 PciDev::writeConfig(offset, data); 312 } else if (offset >= IDE_CTRL_CONF_START && 313 (offset + 1) <= IDE_CTRL_CONF_END) { 314 315 switch (offset) { 316 case IDE_CTRL_CONF_DEV_TIMING: 317 config_regs.sidetim = data; 318 break; 319 case IDE_CTRL_CONF_UDMA_CNTRL: 320 config_regs.udmactl = data; 321 break; 322 case IDE_CTRL_CONF_IDE_CONFIG: 323 config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data); 324 break; 325 case IDE_CTRL_CONF_IDE_CONFIG+1: 326 config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8; 327 break; 328 default: 329 panic("Invalid PCI configuration write for size 1 offset: %#x!\n", 330 offset); 331 } 332 333 } else { 334 panic("Read of unimplemented PCI config. register: %x\n", offset); 335 } 336 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", 337 offset, (uint32_t)data); 338} 339 340void 341IdeController::writeConfig(int offset, const uint16_t data) 342{ 343 if (offset < PCI_DEVICE_SPECIFIC) { 344 PciDev::writeConfig(offset, data); 345 } else if (offset >= IDE_CTRL_CONF_START && 346 (offset + 2) <= IDE_CTRL_CONF_END) { 347 348 switch (offset) { 349 case IDE_CTRL_CONF_PRIM_TIMING: 350 config_regs.idetim0 = data; 351 break; 352 case IDE_CTRL_CONF_SEC_TIMING: 353 config_regs.idetim1 = data; 354 break; 355 case IDE_CTRL_CONF_UDMA_TIMING: 356 config_regs.udmatim = data; 357 break; 358 case IDE_CTRL_CONF_IDE_CONFIG: 359 config_regs.ideconfig = data; 360 break; 361 default: 362 panic("Invalid PCI configuration write for size 2 offset: %#x!\n", 363 offset); 364 } 365 366 } else { 367 panic("Write of unimplemented PCI config. register: %x\n", offset); 368 } 369 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data); 370 371 /* Trap command register writes and enable IO/BM as appropriate. */ 372 if (offset == PCI_COMMAND) { 373 if (letoh(config.command) & PCI_CMD_IOSE) 374 io_enabled = true; 375 else 376 io_enabled = false; 377 378 if (letoh(config.command) & PCI_CMD_BME) 379 bm_enabled = true; 380 else 381 bm_enabled = false; 382 } 383 384} 385 386void 387IdeController::writeConfig(int offset, const uint32_t data) 388{ 389 if (offset < PCI_DEVICE_SPECIFIC) { 390 PciDev::writeConfig(offset, data); 391 } else { 392 panic("Read of unimplemented PCI config. register: %x\n", offset); 393 } 394 395 DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data); 396 397 switch(offset) { 398 case PCI0_BASE_ADDR0: 399 if (BARAddrs[0] != 0) 400 pri_cmd_addr = BARAddrs[0]; 401 break; 402 403 case PCI0_BASE_ADDR1: 404 if (BARAddrs[1] != 0) 405 pri_ctrl_addr = BARAddrs[1]; 406 break; 407 408 case PCI0_BASE_ADDR2: 409 if (BARAddrs[2] != 0) 410 sec_cmd_addr = BARAddrs[2]; 411 break; 412 413 case PCI0_BASE_ADDR3: 414 if (BARAddrs[3] != 0) 415 sec_ctrl_addr = BARAddrs[3]; 416 break; 417 418 case PCI0_BASE_ADDR4: 419 if (BARAddrs[4] != 0) 420 bmi_addr = BARAddrs[4]; 421 break; 422 } 423} 424 425Tick 426IdeController::read(Packet &pkt) 427{ 428 Addr offset; 429 IdeChannel channel; 430 IdeRegType reg_type; 431 int disk; 432 433 uint8_t *data8 = 0 ; 434 uint16_t *data16 = 0; 435 uint32_t *data32 = 0; 436 437 switch(pkt.size) { 438 case sizeof(uint8_t): 439 if (!pkt.data) { 440 data8 = new uint8_t; 441 pkt.data = data8; 442 } else 443 data8 = pkt.data; 444 *data8 = 0; 445 break; 446 case sizeof(uint16_t): 447 if (!pkt.data) { 448 data16 = new uint16_t; 449 pkt.data = (uint8_t*)data16; 450 } else 451 data16 = (uint16_t*)pkt.data; 452 *data16 = 0; 453 break; 454 case sizeof(uint32_t): 455 if (!pkt.data) { 456 data32 = new uint32_t; 457 pkt.data = (uint8_t*)data32; 458 } else 459 data32 = (uint32_t*)pkt.data; 460 *data32 = 0; 461 break; 462 default: 463 panic("Bad IDE read size: %d\n", pkt.size); 464 } 465 466 parseAddr(pkt.addr, offset, channel, reg_type); 467 468 if (!io_enabled) { 469 pkt.result = Success; 470 return pioDelay; 471 } 472 473 switch (reg_type) { 474 case BMI_BLOCK: 475 switch (pkt.size) { 476 case sizeof(uint8_t): 477 *data8 = bmi_regs.data[offset]; 478 break; 479 case sizeof(uint16_t): 480 *data16 = *(uint16_t*)&bmi_regs.data[offset]; 481 break; 482 case sizeof(uint32_t): 483 *data32 = *(uint32_t*)&bmi_regs.data[offset]; 484 break; 485 default: 486 panic("IDE read of BMI reg invalid size: %#x\n", pkt.size); 487 } 488 break; 489 490 case COMMAND_BLOCK: 491 case CONTROL_BLOCK: 492 disk = getDisk(channel); 493 494 if (disks[disk] == NULL) 495 break; 496 497 switch (offset) { 498 case DATA_OFFSET: 499 switch (pkt.size) { 500 case sizeof(uint16_t): 501 disks[disk]->read(offset, reg_type, (uint8_t*)data16); 502 break; 503 504 case sizeof(uint32_t): 505 disks[disk]->read(offset, reg_type, (uint8_t*)data16); 506 disks[disk]->read(offset, reg_type, (uint8_t*)(data16 + sizeof(uint16_t))); 507 break; 508 509 default: 510 panic("IDE read of data reg invalid size: %#x\n", pkt.size); 511 } 512 break; 513 default: 514 if (pkt.size == sizeof(uint8_t)) { 515 disks[disk]->read(offset, reg_type, data8); 516 } else 517 panic("IDE read of command reg of invalid size: %#x\n", pkt.size); 518 } 519 break; 520 default: 521 panic("IDE controller read of unknown register block type!\n"); 522 } 523 if (pkt.size == 1) 524 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 525 offset, pkt.size, (uint32_t)*data8); 526 else if (pkt.size == 2) 527 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 528 offset, pkt.size, *data16); 529 else 530 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 531 offset, pkt.size, *data32); 532 533 pkt.result = Success; 534 return pioDelay; 535} 536 537Tick 538IdeController::write(Packet &pkt) 539{ 540 Addr offset; 541 IdeChannel channel; 542 IdeRegType reg_type; 543 int disk; 544 uint8_t oldVal, newVal; 545 uint8_t data8 = *(uint8_t*)pkt.data; 546 uint32_t data32 = *(uint32_t*)pkt.data; 547 548 549 parseAddr(pkt.addr, offset, channel, reg_type); 550 551 if (!io_enabled) { 552 pkt.result = Success; 553 return pioDelay; 554 } 555 556 switch (reg_type) { 557 case BMI_BLOCK: 558 if (!bm_enabled) { 559 pkt.result = Success; 560 return pioDelay; 561 } 562 563 switch (offset) { 564 // Bus master IDE command register 565 case BMIC1: 566 case BMIC0: 567 if (pkt.size != sizeof(uint8_t)) 568 panic("Invalid BMIC write size: %x\n", pkt.size); 569 570 // select the current disk based on DEV bit 571 disk = getDisk(channel); 572 573 oldVal = bmi_regs.chan[channel].bmic; 574 newVal = data8; 575 576 // if a DMA transfer is in progress, R/W control cannot change 577 if (oldVal & SSBM) { 578 if ((oldVal & RWCON) ^ (newVal & RWCON)) { 579 (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON; 580 } 581 } 582 583 // see if the start/stop bit is being changed 584 if ((oldVal & SSBM) ^ (newVal & SSBM)) { 585 if (oldVal & SSBM) { 586 // stopping DMA transfer 587 DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 588 589 // clear the BMIDEA bit 590 bmi_regs.chan[channel].bmis = 591 bmi_regs.chan[channel].bmis & ~BMIDEA; 592 593 if (disks[disk] == NULL) 594 panic("DMA stop for disk %d which does not exist\n", 595 disk); 596 597 // inform the disk of the DMA transfer abort 598 disks[disk]->abortDma(); 599 } else { 600 // starting DMA transfer 601 DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 602 603 // set the BMIDEA bit 604 bmi_regs.chan[channel].bmis = 605 bmi_regs.chan[channel].bmis | BMIDEA; 606 607 if (disks[disk] == NULL) 608 panic("DMA start for disk %d which does not exist\n", 609 disk); 610 611 // inform the disk of the DMA transfer start 612 disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp)); 613 } 614 } 615 616 // update the register value 617 bmi_regs.chan[channel].bmic = newVal; 618 break; 619 620 // Bus master IDE status register 621 case BMIS0: 622 case BMIS1: 623 if (pkt.size != sizeof(uint8_t)) 624 panic("Invalid BMIS write size: %x\n", pkt.size); 625 626 oldVal = bmi_regs.chan[channel].bmis; 627 newVal = data8; 628 629 // the BMIDEA bit is RO 630 newVal |= (oldVal & BMIDEA); 631 632 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 633 if ((oldVal & IDEINTS) && (newVal & IDEINTS)) 634 newVal &= ~IDEINTS; // clear the interrupt? 635 else 636 (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS; 637 638 if ((oldVal & IDEDMAE) && (newVal & IDEDMAE)) 639 newVal &= ~IDEDMAE; 640 else 641 (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; 642 643 bmi_regs.chan[channel].bmis = newVal; 644 break; 645 646 // Bus master IDE descriptor table pointer register 647 case BMIDTP0: 648 case BMIDTP1: 649 { 650 if (pkt.size != sizeof(uint32_t)) 651 panic("Invalid BMIDTP write size: %x\n", pkt.size); 652 653 bmi_regs.chan[channel].bmidtp = htole(data32 & ~0x3); 654 } 655 break; 656 657 default: 658 if (pkt.size != sizeof(uint8_t) && 659 pkt.size != sizeof(uint16_t) && 660 pkt.size != sizeof(uint32_t)) 661 panic("IDE controller write of invalid write size: %x\n", 662 pkt.size); 663 664 // do a default copy of data into the registers 665 memcpy(&bmi_regs.data[offset], pkt.data, pkt.size); 666 } 667 break; 668 case COMMAND_BLOCK: 669 if (offset == IDE_SELECT_OFFSET) { 670 uint8_t *devBit = &dev[channel]; 671 *devBit = (letoh(data8) & IDE_SELECT_DEV_BIT) ? 1 : 0; 672 } 673 // fall-through ok! 674 case CONTROL_BLOCK: 675 disk = getDisk(channel); 676 677 if (disks[disk] == NULL) 678 break; 679 680 switch (offset) { 681 case DATA_OFFSET: 682 switch (pkt.size) { 683 case sizeof(uint16_t): 684 disks[disk]->write(offset, reg_type, pkt.data); 685 break; 686 687 case sizeof(uint32_t): 688 disks[disk]->write(offset, reg_type, pkt.data); 689 disks[disk]->write(offset, reg_type, pkt.data + 690 sizeof(uint16_t)); 691 break; 692 default: 693 panic("IDE write of data reg invalid size: %#x\n", pkt.size); 694 } 695 break; 696 default: 697 if (pkt.size == sizeof(uint8_t)) { 698 disks[disk]->write(offset, reg_type, pkt.data); 699 } else 700 panic("IDE write of command reg of invalid size: %#x\n", pkt.size); 701 } 702 break; 703 default: 704 panic("IDE controller write of unknown register block type!\n"); 705 } 706 707 if (pkt.size == 1) 708 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 709 offset, pkt.size, (uint32_t)data8); 710 else if (pkt.size == 2) 711 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 712 offset, pkt.size, *(uint16_t*)pkt.data); 713 else 714 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 715 offset, pkt.size, data32); 716 717 718 pkt.result = Success; 719 return pioDelay; 720} 721 722//// 723// Serialization 724//// 725 726void 727IdeController::serialize(std::ostream &os) 728{ 729 // Serialize the PciDev base class 730 PciDev::serialize(os); 731 732 // Serialize register addresses and sizes 733 SERIALIZE_SCALAR(pri_cmd_addr); 734 SERIALIZE_SCALAR(pri_cmd_size); 735 SERIALIZE_SCALAR(pri_ctrl_addr); 736 SERIALIZE_SCALAR(pri_ctrl_size); 737 SERIALIZE_SCALAR(sec_cmd_addr); 738 SERIALIZE_SCALAR(sec_cmd_size); 739 SERIALIZE_SCALAR(sec_ctrl_addr); 740 SERIALIZE_SCALAR(sec_ctrl_size); 741 SERIALIZE_SCALAR(bmi_addr); 742 SERIALIZE_SCALAR(bmi_size); 743 744 // Serialize registers 745 SERIALIZE_ARRAY(bmi_regs.data, 746 sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); 747 SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); 748 SERIALIZE_ARRAY(config_regs.data, 749 sizeof(config_regs.data) / sizeof(config_regs.data[0])); 750 751 // Serialize internal state 752 SERIALIZE_SCALAR(io_enabled); 753 SERIALIZE_SCALAR(bm_enabled); 754 SERIALIZE_ARRAY(cmd_in_progress, 755 sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); 756} 757 758void 759IdeController::unserialize(Checkpoint *cp, const std::string §ion) 760{ 761 // Unserialize the PciDev base class 762 PciDev::unserialize(cp, section); 763 764 // Unserialize register addresses and sizes 765 UNSERIALIZE_SCALAR(pri_cmd_addr); 766 UNSERIALIZE_SCALAR(pri_cmd_size); 767 UNSERIALIZE_SCALAR(pri_ctrl_addr); 768 UNSERIALIZE_SCALAR(pri_ctrl_size); 769 UNSERIALIZE_SCALAR(sec_cmd_addr); 770 UNSERIALIZE_SCALAR(sec_cmd_size); 771 UNSERIALIZE_SCALAR(sec_ctrl_addr); 772 UNSERIALIZE_SCALAR(sec_ctrl_size); 773 UNSERIALIZE_SCALAR(bmi_addr); 774 UNSERIALIZE_SCALAR(bmi_size); 775 776 // Unserialize registers 777 UNSERIALIZE_ARRAY(bmi_regs.data, 778 sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); 779 UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); 780 UNSERIALIZE_ARRAY(config_regs.data, 781 sizeof(config_regs.data) / sizeof(config_regs.data[0])); 782 783 // Unserialize internal state 784 UNSERIALIZE_SCALAR(io_enabled); 785 UNSERIALIZE_SCALAR(bm_enabled); 786 UNSERIALIZE_ARRAY(cmd_in_progress, 787 sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); 788} 789 790#ifndef DOXYGEN_SHOULD_SKIP_THIS 791 792BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) 793 794 SimObjectParam<System *> system; 795 SimObjectParam<Platform *> platform; 796 SimObjectParam<PciConfigAll *> configspace; 797 SimObjectParam<PciConfigData *> configdata; 798 Param<uint32_t> pci_bus; 799 Param<uint32_t> pci_dev; 800 Param<uint32_t> pci_func; 801 Param<Tick> pio_latency; 802 SimObjectVectorParam<IdeDisk *> disks; 803 804END_DECLARE_SIM_OBJECT_PARAMS(IdeController) 805 806BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) 807 808 INIT_PARAM(system, "System pointer"), 809 INIT_PARAM(platform, "Platform pointer"), 810 INIT_PARAM(configspace, "PCI Configspace"), 811 INIT_PARAM(configdata, "PCI Config data"), 812 INIT_PARAM(pci_bus, "PCI bus ID"), 813 INIT_PARAM(pci_dev, "PCI device number"), 814 INIT_PARAM(pci_func, "PCI function code"), 815 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 816 INIT_PARAM(disks, "IDE disks attached to this controller") 817 818END_INIT_SIM_OBJECT_PARAMS(IdeController) 819 820CREATE_SIM_OBJECT(IdeController) 821{ 822 IdeController::Params *params = new IdeController::Params; 823 params->name = getInstanceName(); 824 params->platform = platform; 825 params->system = system; 826 params->configSpace = configspace; 827 params->configData = configdata; 828 params->busNum = pci_bus; 829 params->deviceNum = pci_dev; 830 params->functionNum = pci_func; 831 params->pio_delay = pio_latency; 832 params->disks = disks; 833 return new IdeController(params); 834} 835 836REGISTER_SIM_OBJECT("IdeController", IdeController) 837 838#endif //DOXYGEN_SHOULD_SKIP_THIS 839