ide_ctrl.cc revision 5775
14780SN/A/* 24780SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 34780SN/A * All rights reserved. 44780SN/A * 54780SN/A * Redistribution and use in source and binary forms, with or without 64780SN/A * modification, are permitted provided that the following conditions are 74780SN/A * met: redistributions of source code must retain the above copyright 84780SN/A * notice, this list of conditions and the following disclaimer; 94780SN/A * redistributions in binary form must reproduce the above copyright 104780SN/A * notice, this list of conditions and the following disclaimer in the 114780SN/A * documentation and/or other materials provided with the distribution; 124780SN/A * neither the name of the copyright holders nor the names of its 134780SN/A * contributors may be used to endorse or promote products derived from 144780SN/A * this software without specific prior written permission. 154780SN/A * 164780SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174780SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184780SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194780SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204780SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214780SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224780SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234780SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244780SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254780SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264780SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274780SN/A * 284780SN/A * Authors: Andrew Schultz 294780SN/A * Ali Saidi 304780SN/A * Miguel Serrano 314780SN/A */ 324780SN/A 338229Snate@binkert.org#include <string> 348229Snate@binkert.org 358229Snate@binkert.org#include "base/trace.hh" 368229Snate@binkert.org#include "cpu/intr_control.hh" 378229Snate@binkert.org#include "dev/ide_ctrl.hh" 384780SN/A#include "dev/ide_disk.hh" 398113Sgblack@eecs.umich.edu#include "mem/packet.hh" 404780SN/A#include "mem/packet_access.hh" 414780SN/A#include "params/IdeController.hh" 424780SN/A#include "sim/byteswap.hh" 438108SN/A 448108SN/Ausing namespace std; 454780SN/A 465049SN/A// Bus master IDE registers 475049SN/Aenum BMIRegOffset { 488108SN/A BMICommand = 0x0, 495049SN/A BMIStatus = 0x2, 508108SN/A BMIDescTablePtr = 0x4 514780SN/A}; 524780SN/A 534780SN/A// PCI config space registers 544780SN/Aenum ConfRegOffset { 554780SN/A PrimaryTiming = 0x40, 565049SN/A SecondaryTiming = 0x42, 578108SN/A DeviceTiming = 0x44, 584780SN/A UDMAControl = 0x48, 594780SN/A UDMATiming = 0x4A, 604780SN/A IDEConfig = 0x54 614780SN/A}; 628108SN/A 635049SN/Astatic const uint16_t timeRegWithDecodeEn = 0x8000; 648108SN/A 655049SN/AIdeController::Channel::Channel( 665049SN/A string newName, Addr _cmdSize, Addr _ctrlSize) : 675049SN/A _name(newName), 685049SN/A cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize), 695049SN/A master(NULL), slave(NULL), selected(NULL) 708108SN/A{ 715049SN/A memset(&bmiRegs, 0, sizeof(bmiRegs)); 728108SN/A bmiRegs.status.dmaCap0 = 1; 735049SN/A bmiRegs.status.dmaCap1 = 1; 745049SN/A} 755049SN/A 765049SN/AIdeController::Channel::~Channel() 775049SN/A{ 784780SN/A delete master; 794780SN/A delete slave; 804780SN/A} 818108SN/A 828108SN/AIdeController::IdeController(Params *p) 835049SN/A : PciDev(p), primary(name() + ".primary", BARSize[0], BARSize[1]), 844780SN/A secondary(name() + ".secondary", BARSize[2], BARSize[3]), 855049SN/A bmiAddr(0), bmiSize(BARSize[4]), 868108SN/A primaryTiming(htole(timeRegWithDecodeEn)), 878108SN/A secondaryTiming(htole(timeRegWithDecodeEn)), 888108SN/A deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0), 898108SN/A ioEnabled(false), bmEnabled(false) 908108SN/A{ 918108SN/A if (params()->disks.size() > 3) 928108SN/A panic("IDE controllers support a maximum of 4 devices attached!\n"); 938108SN/A 948108SN/A // Assign the disks to channels 958108SN/A int numDisks = params()->disks.size(); 968108SN/A if (numDisks > 0) 978108SN/A primary.master = params()->disks[0]; 988108SN/A if (numDisks > 1) 998108SN/A primary.slave = params()->disks[1]; 1008108SN/A if (numDisks > 2) 1018108SN/A secondary.master = params()->disks[2]; 1028108SN/A if (numDisks > 3) 1038108SN/A secondary.slave = params()->disks[3]; 1048108SN/A 1058108SN/A for (int i = 0; i < params()->disks.size(); i++) { 1068108SN/A params()->disks[i]->setController(this); 1078108SN/A } 1088108SN/A primary.select(false); 1098108SN/A secondary.select(false); 1108108SN/A} 1118108SN/A 1128108SN/Abool 1138108SN/AIdeController::isDiskSelected(IdeDisk *diskPtr) 1148108SN/A{ 1158108SN/A return (primary.selected == diskPtr || secondary.selected == diskPtr); 1168108SN/A} 1178108SN/A 1188108SN/Avoid 1198108SN/AIdeController::intrPost() 1208108SN/A{ 1218108SN/A primary.bmiRegs.status.intStatus = 1; 1228108SN/A PciDev::intrPost(); 1238108SN/A} 1248108SN/A 1258108SN/Avoid 1268108SN/AIdeController::setDmaComplete(IdeDisk *disk) 1278108SN/A{ 1288108SN/A Channel *channel; 1298108SN/A if (disk == primary.master || disk == primary.slave) { 1308108SN/A channel = &primary; 1318108SN/A } else if (disk == secondary.master || disk == secondary.slave) { 1328108SN/A channel = &secondary; 1338108SN/A } else { 1348108SN/A panic("Unable to find disk based on pointer %#x\n", disk); 1358108SN/A } 1368108SN/A 1378108SN/A channel->bmiRegs.command.startStop = 0; 1388108SN/A channel->bmiRegs.status.active = 0; 1398108SN/A channel->bmiRegs.status.intStatus = 1; 1408108SN/A} 1418108SN/A 1428108SN/ATick 1438108SN/AIdeController::readConfig(PacketPtr pkt) 1448108SN/A{ 1458108SN/A int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 1468108SN/A if (offset < PCI_DEVICE_SPECIFIC) { 1478108SN/A return PciDev::readConfig(pkt); 1488108SN/A } 1498108SN/A 1508108SN/A pkt->allocate(); 1518108SN/A 1528108SN/A switch (pkt->getSize()) { 1538108SN/A case sizeof(uint8_t): 1548108SN/A switch (offset) { 1558108SN/A case DeviceTiming: 1568108SN/A pkt->set<uint8_t>(deviceTiming); 1578108SN/A break; 1588108SN/A case UDMAControl: 1598108SN/A pkt->set<uint8_t>(udmaControl); 1608108SN/A break; 1618108SN/A case PrimaryTiming + 1: 1628108SN/A pkt->set<uint8_t>(bits(htole(primaryTiming), 15, 8)); 1638108SN/A break; 1648108SN/A case SecondaryTiming + 1: 1658108SN/A pkt->set<uint8_t>(bits(htole(secondaryTiming), 15, 8)); 1668108SN/A break; 1678108SN/A case IDEConfig: 1688108SN/A pkt->set<uint8_t>(bits(htole(ideConfig), 7, 0)); 1698108SN/A break; 1708108SN/A case IDEConfig + 1: 1718108SN/A pkt->set<uint8_t>(bits(htole(ideConfig), 15, 8)); 1728108SN/A break; 1738108SN/A default: 1748108SN/A panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", 1758108SN/A offset); 1768108SN/A } 1778108SN/A DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset, 1788108SN/A (uint32_t)pkt->get<uint8_t>()); 1798108SN/A break; 1808108SN/A case sizeof(uint16_t): 1818108SN/A switch (offset) { 1828108SN/A case PrimaryTiming: 1838108SN/A pkt->set<uint16_t>(primaryTiming); 1848108SN/A break; 1858108SN/A case SecondaryTiming: 1868108SN/A pkt->set<uint16_t>(secondaryTiming); 1878108SN/A break; 1888108SN/A case UDMATiming: 1898108SN/A pkt->set<uint16_t>(udmaTiming); 1908108SN/A break; 1918108SN/A case IDEConfig: 1928108SN/A pkt->set<uint16_t>(ideConfig); 1938108SN/A break; 1948108SN/A default: 1958108SN/A panic("Invalid PCI configuration read for size 2 offset: %#x!\n", 1968108SN/A offset); 1978108SN/A } 1988108SN/A DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, 1998108SN/A (uint32_t)pkt->get<uint16_t>()); 2008108SN/A break; 2018108SN/A case sizeof(uint32_t): 2028108SN/A panic("No 32bit reads implemented for this device."); 2038108SN/A DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, 2048108SN/A (uint32_t)pkt->get<uint32_t>()); 2055049SN/A break; 2064780SN/A default: 2074780SN/A panic("invalid access size(?) for PCI configspace!\n"); 2088108SN/A } 2098108SN/A pkt->makeAtomicResponse(); 2104780SN/A return configDelay; 2114780SN/A} 2125049SN/A 2138108SN/A 2144780SN/ATick 2154780SN/AIdeController::writeConfig(PacketPtr pkt) 2164780SN/A{ 2178108SN/A int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 2185049SN/A if (offset < PCI_DEVICE_SPECIFIC) { 2195049SN/A PciDev::writeConfig(pkt); 2205049SN/A } else { 2218108SN/A switch (pkt->getSize()) { 2224780SN/A case sizeof(uint8_t): 2234780SN/A switch (offset) { 2244780SN/A case DeviceTiming: 2254780SN/A deviceTiming = pkt->get<uint8_t>(); 2264780SN/A break; 2274780SN/A case UDMAControl: 2288108SN/A udmaControl = pkt->get<uint8_t>(); 2294780SN/A break; 2304780SN/A case IDEConfig: 2314780SN/A replaceBits(ideConfig, 7, 0, pkt->get<uint8_t>()); 2328108SN/A break; 2338108SN/A case IDEConfig + 1: 2344780SN/A replaceBits(ideConfig, 15, 8, pkt->get<uint8_t>()); 2358108SN/A break; 2364780SN/A default: 2374780SN/A panic("Invalid PCI configuration write " 2388108SN/A "for size 1 offset: %#x!\n", offset); 2398108SN/A } 2404780SN/A DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", 2418108SN/A offset, (uint32_t)pkt->get<uint8_t>()); 2424780SN/A break; 2434780SN/A case sizeof(uint16_t): 2448108SN/A switch (offset) { 2458108SN/A case PrimaryTiming: 2464780SN/A primaryTiming = pkt->get<uint16_t>(); 2474780SN/A break; 2484780SN/A case SecondaryTiming: 2494843SN/A secondaryTiming = pkt->get<uint16_t>(); 2504780SN/A break; 2517071SN/A case UDMATiming: 2524780SN/A udmaTiming = pkt->get<uint16_t>(); 2537071SN/A break; 2544780SN/A case IDEConfig: 2554780SN/A ideConfig = pkt->get<uint16_t>(); 2564780SN/A break; 2574780SN/A default: 2587071SN/A panic("Invalid PCI configuration write " 2594780SN/A "for size 2 offset: %#x!\n", 2604780SN/A offset); 2614780SN/A } 2624780SN/A DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", 2634780SN/A offset, (uint32_t)pkt->get<uint16_t>()); 2644780SN/A break; 2658108SN/A case sizeof(uint32_t): 2664780SN/A panic("Write of unimplemented PCI config. register: %x\n", offset); 2677071SN/A break; 2684780SN/A default: 2698108SN/A panic("invalid access size(?) for PCI configspace!\n"); 2708108SN/A } 2714843SN/A pkt->makeAtomicResponse(); 2724780SN/A } 2734780SN/A 27411321Ssteve.reinhardt@amd.com /* Trap command register writes and enable IO/BM as appropriate as well as 2754780SN/A * BARs. */ 2764780SN/A switch(offset) { 2774780SN/A case PCI0_BASE_ADDR0: 2784780SN/A if (BARAddrs[0] != 0) 2798108SN/A primary.cmdAddr = BARAddrs[0]; 2804780SN/A break; 2817071SN/A 2824780SN/A case PCI0_BASE_ADDR1: 2834780SN/A if (BARAddrs[1] != 0) 2844780SN/A primary.ctrlAddr = BARAddrs[1]; 28511321Ssteve.reinhardt@amd.com break; 2864780SN/A 2878108SN/A case PCI0_BASE_ADDR2: 2884780SN/A if (BARAddrs[2] != 0) 2894780SN/A secondary.cmdAddr = BARAddrs[2]; 2904780SN/A break; 2914780SN/A 2927071SN/A case PCI0_BASE_ADDR3: 2934791SN/A if (BARAddrs[3] != 0) 2944780SN/A secondary.ctrlAddr = BARAddrs[3]; 29511321Ssteve.reinhardt@amd.com break; 2964780SN/A 2974780SN/A case PCI0_BASE_ADDR4: 2984780SN/A if (BARAddrs[4] != 0) 2994780SN/A bmiAddr = BARAddrs[4]; 3004780SN/A break; 3018108SN/A 3024780SN/A case PCI_COMMAND: 3034780SN/A ioEnabled = (config.command & htole(PCI_CMD_IOSE)); 3048108SN/A bmEnabled = (config.command & htole(PCI_CMD_BME)); 3058108SN/A break; 3064780SN/A } 3078108SN/A return configDelay; 3087071SN/A} 3094780SN/A 3104780SN/Avoid 3114780SN/AIdeController::Channel::accessCommand(Addr offset, 3124780SN/A int size, uint8_t *data, bool read) 3134780SN/A{ 3144780SN/A const Addr SelectOffset = 6; 3154780SN/A const uint8_t SelectDevBit = 0x10; 3164780SN/A 3178108SN/A if (!read && offset == SelectOffset) 3184780SN/A select(*data & SelectDevBit); 3194780SN/A 3204780SN/A if (selected == NULL) { 3218108SN/A assert(size == sizeof(uint8_t)); 3228108SN/A *data = 0; 3234795SN/A } else if (read) { 3244795SN/A selected->readCommand(offset, size, data); 3254795SN/A } else { 3264795SN/A selected->writeCommand(offset, size, data); 3278108SN/A } 3284795SN/A} 3298108SN/A 3304795SN/Avoid 3318108SN/AIdeController::Channel::accessControl(Addr offset, 33211321Ssteve.reinhardt@amd.com int size, uint8_t *data, bool read) 3334795SN/A{ 3344795SN/A if (selected == NULL) { 3354795SN/A assert(size == sizeof(uint8_t)); 3364795SN/A *data = 0; 3374795SN/A } else if (read) { 3384795SN/A selected->readControl(offset, size, data); 3394795SN/A } else { 3404795SN/A selected->writeControl(offset, size, data); 3414795SN/A } 3424795SN/A} 3434795SN/A 3448108SN/Avoid 3454795SN/AIdeController::Channel::accessBMI(Addr offset, 3464795SN/A int size, uint8_t *data, bool read) 3474795SN/A{ 3488108SN/A assert(offset + size <= sizeof(BMIRegs)); 3498108SN/A if (read) { 3504795SN/A memcpy(data, (uint8_t *)&bmiRegs + offset, size); 3518108SN/A } else { 3524795SN/A switch (offset) { 3534795SN/A case BMICommand: 3544795SN/A { 3554795SN/A if (size != sizeof(uint8_t)) 3568108SN/A panic("Invalid BMIC write size: %x\n", size); 3578108SN/A 3584795SN/A BMICommandReg oldVal = bmiRegs.command; 3598108SN/A BMICommandReg newVal = *data; 3604795SN/A 3618108SN/A // if a DMA transfer is in progress, R/W control cannot change 3624795SN/A if (oldVal.startStop && oldVal.rw != newVal.rw) 3634795SN/A oldVal.rw = newVal.rw; 3644795SN/A 3654795SN/A if (oldVal.startStop != newVal.startStop) { 3664795SN/A if (selected == NULL) 3674795SN/A panic("DMA start for disk which does not exist\n"); 3684795SN/A 3694795SN/A if (oldVal.startStop) { 3704795SN/A DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 3714795SN/A bmiRegs.status.active = 0; 3724795SN/A 3738108SN/A selected->abortDma(); 3748108SN/A } else { 3754795SN/A DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 3764795SN/A bmiRegs.status.active = 1; 3778108SN/A 3784795SN/A selected->startDma(letoh(bmiRegs.bmidtp)); 3794795SN/A } 3804795SN/A } 3814795SN/A 3824795SN/A bmiRegs.command = newVal; 3834795SN/A } 3844795SN/A break; 3854795SN/A case BMIStatus: 3864795SN/A { 3874795SN/A if (size != sizeof(uint8_t)) 3884795SN/A panic("Invalid BMIS write size: %x\n", size); 3894795SN/A 3904795SN/A BMIStatusReg oldVal = bmiRegs.status; 3914795SN/A BMIStatusReg newVal = *data; 3928108SN/A 3934955SN/A // the BMIDEA bit is read only 3944955SN/A newVal.active = oldVal.active; 3958108SN/A 3964955SN/A // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 3974955SN/A if (oldVal.intStatus && newVal.intStatus) 39811321Ssteve.reinhardt@amd.com newVal.intStatus = 0; // clear the interrupt? 3994955SN/A else 4004795SN/A newVal.intStatus = oldVal.intStatus; 4014795SN/A if (oldVal.dmaError && newVal.dmaError) 4024780SN/A newVal.dmaError = 0; 4034780SN/A else 4048108SN/A newVal.dmaError = oldVal.dmaError; 4054780SN/A 406 bmiRegs.status = newVal; 407 } 408 break; 409 case BMIDescTablePtr: 410 if (size != sizeof(uint32_t)) 411 panic("Invalid BMIDTP write size: %x\n", size); 412 bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3); 413 break; 414 default: 415 if (size != sizeof(uint8_t) && size != sizeof(uint16_t) && 416 size != sizeof(uint32_t)) 417 panic("IDE controller write of invalid write size: %x\n", size); 418 memcpy((uint8_t *)&bmiRegs + offset, data, size); 419 } 420 } 421} 422 423void 424IdeController::dispatchAccess(PacketPtr pkt, bool read) 425{ 426 pkt->allocate(); 427 if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) 428 panic("Bad IDE read size: %d\n", pkt->getSize()); 429 430 if (!ioEnabled) { 431 pkt->makeAtomicResponse(); 432 DPRINTF(IdeCtrl, "io not enabled\n"); 433 return; 434 } 435 436 Addr addr = pkt->getAddr(); 437 int size = pkt->getSize(); 438 uint8_t *dataPtr = pkt->getPtr<uint8_t>(); 439 440 if (addr >= primary.cmdAddr && 441 addr < (primary.cmdAddr + primary.cmdSize)) { 442 addr -= primary.cmdAddr; 443 primary.accessCommand(addr, size, dataPtr, read); 444 } else if (addr >= primary.ctrlAddr && 445 addr < (primary.ctrlAddr + primary.ctrlSize)) { 446 addr -= primary.ctrlAddr; 447 primary.accessControl(addr, size, dataPtr, read); 448 } else if (addr >= secondary.cmdAddr && 449 addr < (secondary.cmdAddr + secondary.cmdSize)) { 450 addr -= secondary.cmdAddr; 451 secondary.accessCommand(addr, size, dataPtr, read); 452 } else if (addr >= secondary.ctrlAddr && 453 addr < (secondary.ctrlAddr + secondary.ctrlSize)) { 454 addr -= secondary.ctrlAddr; 455 secondary.accessControl(addr, size, dataPtr, read); 456 } else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) { 457 if (!read && !bmEnabled) 458 return; 459 addr -= bmiAddr; 460 if (addr < sizeof(Channel::BMIRegs)) { 461 primary.accessBMI(addr, size, dataPtr, read); 462 } else { 463 addr -= sizeof(Channel::BMIRegs); 464 secondary.accessBMI(addr, size, dataPtr, read); 465 } 466 } else { 467 panic("IDE controller access to invalid address: %#x\n", addr); 468 } 469 470 uint32_t data; 471 if (pkt->getSize() == 1) 472 data = pkt->get<uint8_t>(); 473 else if (pkt->getSize() == 2) 474 data = pkt->get<uint16_t>(); 475 else 476 data = pkt->get<uint32_t>(); 477 DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n", 478 read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data); 479 480 pkt->makeAtomicResponse(); 481} 482 483Tick 484IdeController::read(PacketPtr pkt) 485{ 486 dispatchAccess(pkt, true); 487 return pioDelay; 488} 489 490Tick 491IdeController::write(PacketPtr pkt) 492{ 493 dispatchAccess(pkt, false); 494 return pioDelay; 495} 496 497void 498IdeController::serialize(std::ostream &os) 499{ 500 // Serialize the PciDev base class 501 PciDev::serialize(os); 502 503 // Serialize channels 504 primary.serialize(os); 505 secondary.serialize(os); 506 507 // Serialize config registers 508 SERIALIZE_SCALAR(primaryTiming); 509 SERIALIZE_SCALAR(secondaryTiming); 510 SERIALIZE_SCALAR(deviceTiming); 511 SERIALIZE_SCALAR(udmaControl); 512 SERIALIZE_SCALAR(udmaTiming); 513 SERIALIZE_SCALAR(ideConfig); 514 515 // Serialize internal state 516 SERIALIZE_SCALAR(ioEnabled); 517 SERIALIZE_SCALAR(bmEnabled); 518} 519 520void 521IdeController::Channel::serialize(std::ostream &os) 522{ 523 SERIALIZE_SCALAR(cmdAddr); 524 SERIALIZE_SCALAR(cmdSize); 525 SERIALIZE_SCALAR(ctrlAddr); 526 SERIALIZE_SCALAR(ctrlSize); 527 uint8_t command = bmiRegs.command; 528 SERIALIZE_SCALAR(command); 529 SERIALIZE_SCALAR(bmiRegs.reserved0); 530 uint8_t status = bmiRegs.status; 531 SERIALIZE_SCALAR(status); 532 SERIALIZE_SCALAR(bmiRegs.reserved1); 533 SERIALIZE_SCALAR(bmiRegs.bmidtp); 534 SERIALIZE_SCALAR(selectBit); 535} 536 537void 538IdeController::unserialize(Checkpoint *cp, const std::string §ion) 539{ 540 // Unserialize the PciDev base class 541 PciDev::unserialize(cp, section); 542 543 // Unserialize channels 544 primary.unserialize(cp, section); 545 secondary.unserialize(cp, section); 546 547 // Unserialize config registers 548 UNSERIALIZE_SCALAR(primaryTiming); 549 UNSERIALIZE_SCALAR(secondaryTiming); 550 UNSERIALIZE_SCALAR(deviceTiming); 551 UNSERIALIZE_SCALAR(udmaControl); 552 UNSERIALIZE_SCALAR(udmaTiming); 553 UNSERIALIZE_SCALAR(ideConfig); 554 555 // Unserialize internal state 556 UNSERIALIZE_SCALAR(ioEnabled); 557 UNSERIALIZE_SCALAR(bmEnabled); 558} 559 560void 561IdeController::Channel::unserialize( 562 Checkpoint *cp, const std::string §ion) 563{ 564 UNSERIALIZE_SCALAR(cmdAddr); 565 UNSERIALIZE_SCALAR(cmdSize); 566 UNSERIALIZE_SCALAR(ctrlAddr); 567 UNSERIALIZE_SCALAR(ctrlSize); 568 uint8_t command; 569 UNSERIALIZE_SCALAR(command); 570 bmiRegs.command = command; 571 UNSERIALIZE_SCALAR(bmiRegs.reserved0); 572 uint8_t status; 573 UNSERIALIZE_SCALAR(status); 574 bmiRegs.status = status; 575 UNSERIALIZE_SCALAR(bmiRegs.reserved1); 576 UNSERIALIZE_SCALAR(bmiRegs.bmidtp); 577 UNSERIALIZE_SCALAR(selectBit); 578 select(selectBit); 579} 580 581IdeController * 582IdeControllerParams::create() 583{ 584 return new IdeController(this); 585} 586