| /* | |
| * Copyright (c) 2008 The Regents of The University of Michigan | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Ali Saidi | |
| */ | |
| /* @file | |
| * Register and structure descriptions for Intel's I/O AT DMA Engine | |
| */ | |
| #include "base/bitfield.hh" | |
| #include "sim/serialize.hh" | |
| namespace CopyEngineReg { | |
| // General Channel independant registers, 128 bytes starting at 0x00 | |
| const uint32_t GEN_CHANCOUNT = 0x00; | |
| const uint32_t GEN_XFERCAP = 0x01; | |
| const uint32_t GEN_INTRCTRL = 0x03; | |
| const uint32_t GEN_ATTNSTATUS = 0x04; | |
| // Channel specific registers, each block is 128 bytes, starting at 0x80 | |
| const uint32_t CHAN_CONTROL = 0x00; | |
| const uint32_t CHAN_STATUS = 0x04; | |
| const uint32_t CHAN_CHAINADDR = 0x0C; | |
| const uint32_t CHAN_CHAINADDR_LOW = 0x0C; | |
| const uint32_t CHAN_CHAINADDR_HIGH = 0x10; | |
| const uint32_t CHAN_COMMAND = 0x14; | |
| const uint32_t CHAN_CMPLNADDR = 0x18; | |
| const uint32_t CHAN_CMPLNADDR_LOW = 0x18; | |
| const uint32_t CHAN_CMPLNADDR_HIGH = 0x1C; | |
| const uint32_t CHAN_ERROR = 0x28; | |
| const uint32_t DESC_CTRL_INT_GEN = 0x00000001; | |
| const uint32_t DESC_CTRL_SRC_SN = 0x00000002; | |
| const uint32_t DESC_CTRL_DST_SN = 0x00000004; | |
| const uint32_t DESC_CTRL_CP_STS = 0x00000008; | |
| const uint32_t DESC_CTRL_FRAME = 0x00000010; | |
| const uint32_t DESC_CTRL_NULL = 0x00000020; | |
| struct DmaDesc { | |
| uint32_t len; | |
| uint32_t command; | |
| Addr src; | |
| Addr dest; | |
| Addr next; | |
| uint64_t reserved1; | |
| uint64_t reserved2; | |
| uint64_t user1; | |
| uint64_t user2; | |
| }; | |
| #define ADD_FIELD8(NAME, OFFSET, BITS) \ | |
| inline uint8_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ | |
| inline void NAME(uint8_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } | |
| #define ADD_FIELD16(NAME, OFFSET, BITS) \ | |
| inline uint16_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ | |
| inline void NAME(uint16_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } | |
| #define ADD_FIELD32(NAME, OFFSET, BITS) \ | |
| inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ | |
| inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } | |
| #define ADD_FIELD64(NAME, OFFSET, BITS) \ | |
| inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ | |
| inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } | |
| template<class T> | |
| struct Reg { | |
| T _data; | |
| T operator()() { return _data; } | |
| const Reg<T> &operator=(T d) { _data = d; return *this;} | |
| bool operator==(T d) { return d == _data; } | |
| void operator()(T d) { _data = d; } | |
| Reg() { _data = 0; } | |
| void serialize(CheckpointOut &cp) const | |
| { | |
| SERIALIZE_SCALAR(_data); | |
| } | |
| void unserialize(CheckpointIn &cp) | |
| { | |
| UNSERIALIZE_SCALAR(_data); | |
| } | |
| }; | |
| struct Regs : public Serializable { | |
| uint8_t chanCount; | |
| uint8_t xferCap; | |
| struct INTRCTRL : public Reg<uint8_t> { // 0x03 | |
| using Reg<uint8_t>::operator =; | |
| ADD_FIELD8(master_int_enable,0,1); | |
| ADD_FIELD8(interrupt_status,1,1); | |
| ADD_FIELD8(interrupt,2,1); | |
| }; | |
| INTRCTRL intrctrl; | |
| uint32_t attnStatus; // Read clears | |
| void serialize(CheckpointOut &cp) const override | |
| { | |
| SERIALIZE_SCALAR(chanCount); | |
| SERIALIZE_SCALAR(xferCap); | |
| paramOut(cp, "intrctrl", intrctrl._data); | |
| SERIALIZE_SCALAR(attnStatus); | |
| } | |
| void unserialize(CheckpointIn &cp) override | |
| { | |
| UNSERIALIZE_SCALAR(chanCount); | |
| UNSERIALIZE_SCALAR(xferCap); | |
| paramIn(cp, "intrctrl", intrctrl._data); | |
| UNSERIALIZE_SCALAR(attnStatus); | |
| } | |
| }; | |
| struct ChanRegs : public Serializable { | |
| struct CHANCTRL : public Reg<uint16_t> { // channelX + 0x00 | |
| using Reg<uint16_t>::operator =; | |
| ADD_FIELD16(interrupt_disable,0,1); | |
| ADD_FIELD16(error_completion_enable, 2,1); | |
| ADD_FIELD16(any_error_abort_enable,3,1); | |
| ADD_FIELD16(error_int_enable,4,1); | |
| ADD_FIELD16(desc_addr_snoop_control,5,1); | |
| ADD_FIELD16(in_use, 8,1); | |
| }; | |
| CHANCTRL ctrl; | |
| struct CHANSTS : public Reg<uint64_t> { // channelX + 0x04 | |
| ADD_FIELD64(dma_transfer_status, 0, 3); | |
| ADD_FIELD64(unaffiliated_error, 3, 1); | |
| ADD_FIELD64(soft_error, 4, 1); | |
| ADD_FIELD64(compl_desc_addr, 6, 58); | |
| }; | |
| CHANSTS status; | |
| uint64_t descChainAddr; | |
| struct CHANCMD : public Reg<uint8_t> { // channelX + 0x14 | |
| ADD_FIELD8(start_dma,0,1); | |
| ADD_FIELD8(append_dma,1,1); | |
| ADD_FIELD8(suspend_dma,2,1); | |
| ADD_FIELD8(abort_dma,3,1); | |
| ADD_FIELD8(resume_dma,4,1); | |
| ADD_FIELD8(reset_dma,5,1); | |
| }; | |
| CHANCMD command; | |
| uint64_t completionAddr; | |
| struct CHANERR : public Reg<uint32_t> { // channel X + 0x28 | |
| ADD_FIELD32(source_addr_error,0,1); | |
| ADD_FIELD32(dest_addr_error,1,1); | |
| ADD_FIELD32(ndesc_addr_error,2,1); | |
| ADD_FIELD32(desc_error,3,1); | |
| ADD_FIELD32(chain_addr_error,4,1); | |
| ADD_FIELD32(chain_cmd_error,5,1); | |
| ADD_FIELD32(chipset_parity_error,6,1); | |
| ADD_FIELD32(dma_parity_error,7,1); | |
| ADD_FIELD32(read_data_error,8,1); | |
| ADD_FIELD32(write_data_error,9,1); | |
| ADD_FIELD32(desc_control_error,10,1); | |
| ADD_FIELD32(desc_len_error,11,1); | |
| ADD_FIELD32(completion_addr_error,12,1); | |
| ADD_FIELD32(interrupt_config_error,13,1); | |
| ADD_FIELD32(soft_error,14,1); | |
| ADD_FIELD32(unaffiliated_error,15,1); | |
| }; | |
| CHANERR error; | |
| void serialize(CheckpointOut &cp) const override | |
| { | |
| paramOut(cp, "ctrl", ctrl._data); | |
| paramOut(cp, "status", status._data); | |
| SERIALIZE_SCALAR(descChainAddr); | |
| paramOut(cp, "command", command._data); | |
| SERIALIZE_SCALAR(completionAddr); | |
| paramOut(cp, "error", error._data); | |
| } | |
| void unserialize(CheckpointIn &cp) override | |
| { | |
| paramIn(cp, "ctrl", ctrl._data); | |
| paramIn(cp, "status", status._data); | |
| UNSERIALIZE_SCALAR(descChainAddr); | |
| paramIn(cp, "command", command._data); | |
| UNSERIALIZE_SCALAR(completionAddr); | |
| paramIn(cp, "error", error._data); | |
| } | |
| }; | |
| } // namespace CopyEngineReg | |