226 lines
7.5 KiB
C++
226 lines
7.5 KiB
C++
|
/*
|
||
|
* 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(std::ostream &os)
|
||
|
{
|
||
|
SERIALIZE_SCALAR(_data);
|
||
|
}
|
||
|
void unserialize(Checkpoint *cp, const std::string §ion)
|
||
|
{
|
||
|
UNSERIALIZE_SCALAR(_data);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
struct Regs {
|
||
|
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(std::ostream &os)
|
||
|
{
|
||
|
SERIALIZE_SCALAR(chanCount);
|
||
|
SERIALIZE_SCALAR(xferCap);
|
||
|
paramOut(os, "intrctrl", intrctrl._data);
|
||
|
SERIALIZE_SCALAR(attnStatus);
|
||
|
}
|
||
|
|
||
|
void unserialize(Checkpoint *cp, const std::string §ion)
|
||
|
{
|
||
|
UNSERIALIZE_SCALAR(chanCount);
|
||
|
UNSERIALIZE_SCALAR(xferCap);
|
||
|
paramIn(cp, section, "intrctrl", intrctrl._data);
|
||
|
UNSERIALIZE_SCALAR(attnStatus);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
struct ChanRegs {
|
||
|
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(std::ostream &os)
|
||
|
{
|
||
|
paramOut(os, "ctrl", ctrl._data);
|
||
|
paramOut(os, "status", status._data);
|
||
|
SERIALIZE_SCALAR(descChainAddr);
|
||
|
paramOut(os, "command", command._data);
|
||
|
SERIALIZE_SCALAR(completionAddr);
|
||
|
paramOut(os, "error", error._data);
|
||
|
}
|
||
|
|
||
|
void unserialize(Checkpoint *cp, const std::string §ion)
|
||
|
{
|
||
|
paramIn(cp, section, "ctrl", ctrl._data);
|
||
|
paramIn(cp, section, "status", status._data);
|
||
|
UNSERIALIZE_SCALAR(descChainAddr);
|
||
|
paramIn(cp, section, "command", command._data);
|
||
|
UNSERIALIZE_SCALAR(completionAddr);
|
||
|
paramIn(cp, section, "error", error._data);
|
||
|
}
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
} //namespace CopyEngineReg
|
||
|
|
||
|
|