ide_disk.hh revision 5999
12SN/A/* 29955SGeoffrey.Blake@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 39955SGeoffrey.Blake@arm.com * All rights reserved. 49955SGeoffrey.Blake@arm.com * 59955SGeoffrey.Blake@arm.com * Redistribution and use in source and binary forms, with or without 69955SGeoffrey.Blake@arm.com * modification, are permitted provided that the following conditions are 79955SGeoffrey.Blake@arm.com * met: redistributions of source code must retain the above copyright 89955SGeoffrey.Blake@arm.com * notice, this list of conditions and the following disclaimer; 99955SGeoffrey.Blake@arm.com * redistributions in binary form must reproduce the above copyright 109955SGeoffrey.Blake@arm.com * notice, this list of conditions and the following disclaimer in the 119955SGeoffrey.Blake@arm.com * documentation and/or other materials provided with the distribution; 129955SGeoffrey.Blake@arm.com * neither the name of the copyright holders nor the names of its 139955SGeoffrey.Blake@arm.com * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 157778Sgblack@eecs.umich.edu * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Andrew Schultz 292SN/A */ 302SN/A 312SN/A/** @file 322SN/A * Device model for an IDE disk 332SN/A */ 342SN/A 352SN/A#ifndef __IDE_DISK_HH__ 362SN/A#define __IDE_DISK_HH__ 372SN/A 382SN/A#include "base/statistics.hh" 392SN/A#include "dev/disk_image.hh" 402665Ssaidi@eecs.umich.edu#include "dev/ide_atareg.h" 412665Ssaidi@eecs.umich.edu#include "dev/ide_ctrl.hh" 427778Sgblack@eecs.umich.edu#include "dev/ide_wdcreg.h" 439955SGeoffrey.Blake@arm.com#include "dev/io_device.hh" 442SN/A#include "sim/eventq.hh" 452SN/A#include "params/IdeDisk.hh" 468607Sgblack@eecs.umich.edu 476712Snate@binkert.org 482SN/Aclass ChunkGenerator; 492SN/A 502SN/A#define DMA_BACKOFF_PERIOD 200 5156SN/A 526216Snate@binkert.org#define MAX_DMA_SIZE (131072) // 128K 536214Snate@binkert.org#define MAX_MULTSECT (128) 542SN/A 551078SN/A#define PRD_BASE_MASK 0xfffffffe 561114SN/A#define PRD_COUNT_MASK 0xfffe 571114SN/A#define PRD_EOT_MASK 0x8000 581114SN/A 591114SN/Atypedef struct PrdEntry { 601114SN/A uint32_t baseAddr; 611114SN/A uint16_t byteCount; 621114SN/A uint16_t endOfTable; 631114SN/A} PrdEntry_t; 641114SN/A 6510251Satgutier@umich.educlass PrdTableEntry { 6610251Satgutier@umich.edu public: 671114SN/A PrdEntry_t entry; 681114SN/A 691114SN/A uint32_t getBaseAddr() 701114SN/A { 7110251Satgutier@umich.edu return (entry.baseAddr & PRD_BASE_MASK); 7210251Satgutier@umich.edu } 731114SN/A 741114SN/A uint32_t getByteCount() 751114SN/A { 761114SN/A return ((entry.byteCount == 0) ? MAX_DMA_SIZE : 771114SN/A (entry.byteCount & PRD_COUNT_MASK)); 781114SN/A } 791114SN/A 801114SN/A uint16_t getEOT() 811114SN/A { 821114SN/A return (entry.endOfTable & PRD_EOT_MASK); 831114SN/A } 841114SN/A}; 851114SN/A 861114SN/A#define DATA_OFFSET (0) 871114SN/A#define ERROR_OFFSET (1) 881114SN/A#define FEATURES_OFFSET (1) 891114SN/A#define NSECTOR_OFFSET (2) 901114SN/A#define SECTOR_OFFSET (3) 911114SN/A#define LCYL_OFFSET (4) 921114SN/A#define HCYL_OFFSET (5) 931114SN/A#define SELECT_OFFSET (6) 941114SN/A#define DRIVE_OFFSET (6) 951114SN/A#define STATUS_OFFSET (7) 961114SN/A#define COMMAND_OFFSET (7) 971114SN/A 981114SN/A#define CONTROL_OFFSET (2) 991114SN/A#define ALTSTAT_OFFSET (2) 1001114SN/A 1011114SN/A#define SELECT_DEV_BIT 0x10 1021114SN/A#define CONTROL_RST_BIT 0x04 1031114SN/A#define CONTROL_IEN_BIT 0x02 1041114SN/A#define STATUS_BSY_BIT 0x80 1051114SN/A#define STATUS_DRDY_BIT 0x40 1061114SN/A#define STATUS_DRQ_BIT 0x08 1071114SN/A#define STATUS_SEEK_BIT 0x10 1081114SN/A#define STATUS_DF_BIT 0x20 1091114SN/A#define DRIVE_LBA_BIT 0x40 1101114SN/A 1111114SN/A#define DEV0 (0) 1121114SN/A#define DEV1 (1) 1131114SN/A 1141114SN/Atypedef struct CommandReg { 1151114SN/A uint16_t data; 1162SN/A uint8_t error; 1171114SN/A uint8_t sec_count; 1182SN/A uint8_t sec_num; 1192SN/A uint8_t cyl_low; 1201114SN/A uint8_t cyl_high; 1212SN/A union { 1222SN/A uint8_t drive; 1232SN/A uint8_t head; 1241114SN/A }; 1251114SN/A uint8_t command; 1262SN/A} CommandReg_t; 12710252Satgutier@umich.edu 1281114SN/Atypedef enum Events { 1291114SN/A None = 0, 1301114SN/A Transfer, 1311114SN/A ReadWait, 1321114SN/A WriteWait, 1331114SN/A PrdRead, 1341114SN/A DmaRead, 1351114SN/A DmaWrite 1362SN/A} Events_t; 1372SN/A 1387777Sgblack@eecs.umich.edutypedef enum DevAction { 1397777Sgblack@eecs.umich.edu ACT_NONE = 0, 1407777Sgblack@eecs.umich.edu ACT_CMD_WRITE, 1417777Sgblack@eecs.umich.edu ACT_CMD_COMPLETE, 1427777Sgblack@eecs.umich.edu ACT_CMD_ERROR, 1437777Sgblack@eecs.umich.edu ACT_SELECT_WRITE, 1447777Sgblack@eecs.umich.edu ACT_STAT_READ, 1457777Sgblack@eecs.umich.edu ACT_DATA_READY, 1467777Sgblack@eecs.umich.edu ACT_DATA_READ_BYTE, 1477777Sgblack@eecs.umich.edu ACT_DATA_READ_SHORT, 1487777Sgblack@eecs.umich.edu ACT_DATA_WRITE_BYTE, 1497777Sgblack@eecs.umich.edu ACT_DATA_WRITE_SHORT, 1507777Sgblack@eecs.umich.edu ACT_DMA_READY, 1517777Sgblack@eecs.umich.edu ACT_DMA_DONE, 1527777Sgblack@eecs.umich.edu ACT_SRST_SET, 1537777Sgblack@eecs.umich.edu ACT_SRST_CLEAR 1547777Sgblack@eecs.umich.edu} DevAction_t; 1557777Sgblack@eecs.umich.edu 1567777Sgblack@eecs.umich.edutypedef enum DevState { 1577814Sgblack@eecs.umich.edu // Device idle 1587814Sgblack@eecs.umich.edu Device_Idle_S = 0, 1597777Sgblack@eecs.umich.edu Device_Idle_SI, 1607777Sgblack@eecs.umich.edu Device_Idle_NS, 1617777Sgblack@eecs.umich.edu 1627777Sgblack@eecs.umich.edu // Software reset 1637777Sgblack@eecs.umich.edu Device_Srst, 1647777Sgblack@eecs.umich.edu 1657777Sgblack@eecs.umich.edu // Non-data commands 1667777Sgblack@eecs.umich.edu Command_Execution, 1677777Sgblack@eecs.umich.edu 1687777Sgblack@eecs.umich.edu // PIO data-in (data to host) 1697777Sgblack@eecs.umich.edu Prepare_Data_In, 1707777Sgblack@eecs.umich.edu Data_Ready_INTRQ_In, 1717777Sgblack@eecs.umich.edu Transfer_Data_In, 1727777Sgblack@eecs.umich.edu 1737777Sgblack@eecs.umich.edu // PIO data-out (data from host) 1747777Sgblack@eecs.umich.edu Prepare_Data_Out, 1757777Sgblack@eecs.umich.edu Data_Ready_INTRQ_Out, 1767777Sgblack@eecs.umich.edu Transfer_Data_Out, 1777777Sgblack@eecs.umich.edu 1787777Sgblack@eecs.umich.edu // DMA protocol 1797777Sgblack@eecs.umich.edu Prepare_Data_Dma, 1807777Sgblack@eecs.umich.edu Transfer_Data_Dma 1817777Sgblack@eecs.umich.edu} DevState_t; 1827777Sgblack@eecs.umich.edu 1837777Sgblack@eecs.umich.edutypedef enum DmaState { 1847777Sgblack@eecs.umich.edu Dma_Idle = 0, 1857777Sgblack@eecs.umich.edu Dma_Start, 1867777Sgblack@eecs.umich.edu Dma_Transfer 1877777Sgblack@eecs.umich.edu} DmaState_t; 1887777Sgblack@eecs.umich.edu 1897777Sgblack@eecs.umich.educlass PhysicalMemory; 1907777Sgblack@eecs.umich.educlass IdeController; 1917777Sgblack@eecs.umich.edu 1927777Sgblack@eecs.umich.edu/** 1937777Sgblack@eecs.umich.edu * IDE Disk device model 1947777Sgblack@eecs.umich.edu */ 1957777Sgblack@eecs.umich.educlass IdeDisk : public SimObject 1967777Sgblack@eecs.umich.edu{ 1977777Sgblack@eecs.umich.edu protected: 1987777Sgblack@eecs.umich.edu /** The IDE controller for this disk. */ 1997777Sgblack@eecs.umich.edu IdeController *ctrl; 2007777Sgblack@eecs.umich.edu /** The image that contains the data of this disk. */ 2017777Sgblack@eecs.umich.edu DiskImage *image; 2027777Sgblack@eecs.umich.edu 2037777Sgblack@eecs.umich.edu protected: 2047777Sgblack@eecs.umich.edu /** The disk delay in microseconds. */ 2051078SN/A int diskDelay; 2061114SN/A 2071078SN/A private: 2081114SN/A /** Drive identification structure for this disk */ 2091114SN/A struct ataparams driveID; 2101078SN/A /** Data buffer for transfers */ 2111114SN/A uint8_t *dataBuffer; 2121114SN/A /** Number of bytes in command data transfer */ 2131114SN/A uint32_t cmdBytes; 2141114SN/A /** Number of bytes left in command data transfer */ 2151114SN/A uint32_t cmdBytesLeft; 2161114SN/A /** Number of bytes left in DRQ block */ 2171114SN/A uint32_t drqBytesLeft; 2181114SN/A /** Current sector in access */ 2191114SN/A uint32_t curSector; 2201114SN/A /** Command block registers */ 2211114SN/A CommandReg_t cmdReg; 2221114SN/A /** Status register */ 2239955SGeoffrey.Blake@arm.com uint8_t status; 2249955SGeoffrey.Blake@arm.com /** Interrupt enable bit */ 2259955SGeoffrey.Blake@arm.com bool nIENBit; 2269955SGeoffrey.Blake@arm.com /** Device state */ 2279955SGeoffrey.Blake@arm.com DevState_t devState; 2289955SGeoffrey.Blake@arm.com /** Dma state */ 2299955SGeoffrey.Blake@arm.com DmaState_t dmaState; 2309955SGeoffrey.Blake@arm.com /** Dma transaction is a read */ 2319955SGeoffrey.Blake@arm.com bool dmaRead; 2329955SGeoffrey.Blake@arm.com /** PRD table base address */ 2331114SN/A uint32_t curPrdAddr; 2349955SGeoffrey.Blake@arm.com /** PRD entry */ 2359955SGeoffrey.Blake@arm.com PrdTableEntry curPrd; 2369955SGeoffrey.Blake@arm.com /** Device ID (master=0/slave=1) */ 2379955SGeoffrey.Blake@arm.com int devID; 2389955SGeoffrey.Blake@arm.com /** Interrupt pending */ 2399955SGeoffrey.Blake@arm.com bool intrPending; 2409955SGeoffrey.Blake@arm.com 2419955SGeoffrey.Blake@arm.com Stats::Scalar dmaReadFullPages; 2429955SGeoffrey.Blake@arm.com Stats::Scalar dmaReadBytes; 2439955SGeoffrey.Blake@arm.com Stats::Scalar dmaReadTxs; 2449955SGeoffrey.Blake@arm.com Stats::Scalar dmaWriteFullPages; 2451114SN/A Stats::Scalar dmaWriteBytes; 2461114SN/A Stats::Scalar dmaWriteTxs; 2471114SN/A Stats::Formula rdBandwidth; 2489955SGeoffrey.Blake@arm.com Stats::Formula wrBandwidth; 2499955SGeoffrey.Blake@arm.com Stats::Formula totBandwidth; 2509955SGeoffrey.Blake@arm.com Stats::Formula totBytes; 2519955SGeoffrey.Blake@arm.com 2529955SGeoffrey.Blake@arm.com public: 2539955SGeoffrey.Blake@arm.com typedef IdeDiskParams Params; 2549955SGeoffrey.Blake@arm.com IdeDisk(const Params *p); 2559955SGeoffrey.Blake@arm.com 2569955SGeoffrey.Blake@arm.com /** 2579955SGeoffrey.Blake@arm.com * Delete the data buffer. 2581114SN/A */ 2591114SN/A ~IdeDisk(); 2601114SN/A 2611114SN/A /** 2621114SN/A * Reset the device state 2631114SN/A */ 2641114SN/A void reset(int id); 2651114SN/A 2661114SN/A /** 2671114SN/A * Register Statistics 2681114SN/A */ 2691114SN/A void regStats(); 2701114SN/A 2711114SN/A /** 2721114SN/A * Set the controller for this device 2731114SN/A * @param c The IDE controller 2741114SN/A */ 2751114SN/A void setController(IdeController *c) { 2761114SN/A if (ctrl) panic("Cannot change the controller once set!\n"); 2771114SN/A ctrl = c; 2781114SN/A } 2791114SN/A 2809955SGeoffrey.Blake@arm.com // Device register read/write 2819955SGeoffrey.Blake@arm.com void readCommand(const Addr offset, int size, uint8_t *data); 2829955SGeoffrey.Blake@arm.com void readControl(const Addr offset, int size, uint8_t *data); 2839955SGeoffrey.Blake@arm.com void writeCommand(const Addr offset, int size, const uint8_t *data); 2849955SGeoffrey.Blake@arm.com void writeControl(const Addr offset, int size, const uint8_t *data); 2859955SGeoffrey.Blake@arm.com 2869955SGeoffrey.Blake@arm.com // Start/abort functions 2879955SGeoffrey.Blake@arm.com void startDma(const uint32_t &prdTableBase); 2889955SGeoffrey.Blake@arm.com void abortDma(); 2899955SGeoffrey.Blake@arm.com 2909955SGeoffrey.Blake@arm.com private: 2919955SGeoffrey.Blake@arm.com void startCommand(); 2929955SGeoffrey.Blake@arm.com 2939955SGeoffrey.Blake@arm.com // Interrupt management 2949955SGeoffrey.Blake@arm.com void intrPost(); 2959955SGeoffrey.Blake@arm.com void intrClear(); 2969955SGeoffrey.Blake@arm.com 2979955SGeoffrey.Blake@arm.com // DMA stuff 2989955SGeoffrey.Blake@arm.com void doDmaTransfer(); 2999955SGeoffrey.Blake@arm.com friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>; 3009955SGeoffrey.Blake@arm.com EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent; 3019955SGeoffrey.Blake@arm.com 3029955SGeoffrey.Blake@arm.com void doDmaDataRead(); 3039955SGeoffrey.Blake@arm.com 3049955SGeoffrey.Blake@arm.com void doDmaRead(); 3059955SGeoffrey.Blake@arm.com ChunkGenerator *dmaReadCG; 3069955SGeoffrey.Blake@arm.com friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>; 3079955SGeoffrey.Blake@arm.com EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent; 3089955SGeoffrey.Blake@arm.com 3099955SGeoffrey.Blake@arm.com void doDmaDataWrite(); 3109955SGeoffrey.Blake@arm.com 3119955SGeoffrey.Blake@arm.com void doDmaWrite(); 3129955SGeoffrey.Blake@arm.com ChunkGenerator *dmaWriteCG; 3139955SGeoffrey.Blake@arm.com friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>; 3149955SGeoffrey.Blake@arm.com EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent; 3159955SGeoffrey.Blake@arm.com 3169955SGeoffrey.Blake@arm.com void dmaPrdReadDone(); 3179955SGeoffrey.Blake@arm.com friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>; 3189955SGeoffrey.Blake@arm.com EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent; 3199955SGeoffrey.Blake@arm.com 3209955SGeoffrey.Blake@arm.com void dmaReadDone(); 3219955SGeoffrey.Blake@arm.com friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>; 3229955SGeoffrey.Blake@arm.com EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent; 3239955SGeoffrey.Blake@arm.com 3249955SGeoffrey.Blake@arm.com void dmaWriteDone(); 3259955SGeoffrey.Blake@arm.com friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>; 3269955SGeoffrey.Blake@arm.com EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent; 3279955SGeoffrey.Blake@arm.com 3289955SGeoffrey.Blake@arm.com // Disk image read/write 3299955SGeoffrey.Blake@arm.com void readDisk(uint32_t sector, uint8_t *data); 3309955SGeoffrey.Blake@arm.com void writeDisk(uint32_t sector, uint8_t *data); 3319955SGeoffrey.Blake@arm.com 3329955SGeoffrey.Blake@arm.com // State machine management 3339955SGeoffrey.Blake@arm.com void updateState(DevAction_t action); 3349955SGeoffrey.Blake@arm.com 3359955SGeoffrey.Blake@arm.com // Utility functions 3369955SGeoffrey.Blake@arm.com bool isBSYSet() { return (status & STATUS_BSY_BIT); } 3379955SGeoffrey.Blake@arm.com bool isIENSet() { return nIENBit; } 3389955SGeoffrey.Blake@arm.com bool isDEVSelect(); 3399955SGeoffrey.Blake@arm.com 3409955SGeoffrey.Blake@arm.com void setComplete() 3419955SGeoffrey.Blake@arm.com { 3429955SGeoffrey.Blake@arm.com // clear out the status byte 3439955SGeoffrey.Blake@arm.com status = 0; 3449955SGeoffrey.Blake@arm.com // set the DRDY bit 3459955SGeoffrey.Blake@arm.com status |= STATUS_DRDY_BIT; 3469955SGeoffrey.Blake@arm.com // set the SEEK bit 3479955SGeoffrey.Blake@arm.com status |= STATUS_SEEK_BIT; 3489955SGeoffrey.Blake@arm.com } 3499955SGeoffrey.Blake@arm.com 3509955SGeoffrey.Blake@arm.com uint32_t getLBABase() 3519955SGeoffrey.Blake@arm.com { 3529955SGeoffrey.Blake@arm.com return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) | 3539955SGeoffrey.Blake@arm.com (cmdReg.cyl_low << 8) | (cmdReg.sec_num)); 3549955SGeoffrey.Blake@arm.com } 3559955SGeoffrey.Blake@arm.com 3561114SN/A inline Addr pciToDma(Addr pciAddr); 3571114SN/A 3581114SN/A /** 3591114SN/A * Serialize this object to the given output stream. 3601114SN/A * @param os The stream to serialize to. 3611114SN/A */ 3621114SN/A void serialize(std::ostream &os); 3631114SN/A 3641114SN/A /** 3651114SN/A * Reconstruct the state of this object from a checkpoint. 3661114SN/A * @param cp The checkpoint to use. 3671114SN/A * @param section The section name describing this object. 3681114SN/A */ 3691114SN/A void unserialize(Checkpoint *cp, const std::string §ion); 3701114SN/A}; 3711114SN/A 3721114SN/A 3731114SN/A#endif // __IDE_DISK_HH__ 3741114SN/A