20#include "BusMasterIde.h"
21#include "pedigree/kernel/LockGuard.h"
22#include "pedigree/kernel/Log.h"
23#include "pedigree/kernel/processor/IoBase.h"
24#include "pedigree/kernel/processor/MemoryRegion.h"
25#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
26#include "pedigree/kernel/processor/Processor.h"
27#include "pedigree/kernel/processor/ProcessorInformation.h"
28#include "pedigree/kernel/processor/VirtualAddressSpace.h"
29#include "pedigree/kernel/processor/types.h"
30#include "pedigree/kernel/utilities/new"
32BusMasterIde::BusMasterIde()
36 m_LastPrdTableOffset(0),
38 m_PrdTableMemRegion(
"bus-master-ide"),
41BusMasterIde::~BusMasterIde() {
55 if (pBase->
size() != 8)
63 ERROR(
"BusMasterIde: Couldn't allocate the PRD table!");
68 NOTICE(
"BusMasterIde: PRD table at v="
86 return m_bActive.compareAndSwap(
false,
true);
91 if (!buffer || !nBytes || !
m_pBase)
94 ERROR(
"BusMasterIde::add called without transaction ownership");
108 if (va.
isMapped(
reinterpret_cast<void*
>(buffer))) {
111 size_t nRemainingBytes = nBytes, currOffset = 0, i = 0;
117 void* loc =
reinterpret_cast<void*
>(buffer + currOffset);
119 physical_uintptr_t physPage = 0;
121 va.
getMapping(
reinterpret_cast<void*
>(buffer + currOffset), physPage, flags);
126 if (physPage >= (1ULL << 32ULL)) {
128 "BusMasterIde: physical pages must be in the first 4GB "
129 "of address space [given page: "
130 <<
Hex << physPage <<
"]!");
136 size_t pageOffset = 0;
138 pageOffset = (buffer & 0xFFF);
146 size_t transferSize = nRemainingBytes;
147 if (transferSize > 4096)
148 transferSize = 4096 - pageOffset;
156 currOffset += transferSize;
157 nRemainingBytes -= transferSize;
160 if (!nRemainingBytes)
166 FATAL(
"BusMasterIde: Part of the incoming buffer was not mapped (" << loc <<
")!");
185 ERROR(
"BusMasterIde::begin called without transaction ownership");
192 if (!(statusReg & 0x1)) {
199 FATAL(
"BusMaster IDE status and command registers don't make sense");
200 cmdReg = (cmdReg & 0xF6) | 0x1 | (bWrite ? 0 : 8);
204 WARNING(
"BusMaster IDE hit a bad status in begin(): " << statusReg);
218 return (statusReg & 0x4);
228 return (statusReg & 0x2);
238 return (statusReg & 0x1) == 0;
250 EMIT_IF(BusMasterVerboseLogging) {
251 if ((statusReg & 0x1) && (!(statusReg & 0x4))) {
253 NOTICE(
"BusMasterIde: aborting transfer in progress");
254 }
else if ((!(statusReg & 0x1)) && (statusReg & 0x4)) {
256 NOTICE(
"BusMasterIde: successful transfer, exact transfer size");
257 }
else if ((statusReg & 0x1) && (statusReg & 0x4)) {
259 NOTICE(
"BusMasterIde: successful transfer, more buffer space than needed");
262 NOTICE(
"Status register = " << statusReg <<
".");
263 if (!(statusReg & 0x1)) {
264 NOTICE(
"BusMasterIde: not enough buffer space provided");
266 NOTICE(
"BusMasterIde: device/controller signalled an error");
286 if (!
m_bActive.compareAndSwap(
false,
true)) {
bool add(uintptr_t buffer, size_t nBytes)
Adds a buffer to a DMA transaction.
bool hasError()
Determines if an ERROR has occurred on this channel.
size_t m_LastPrdTableOffset
bool completeIdleTransaction()
bool hasCompleted()
Determines if the CURRENT TRANSFER has completed.
bool initialise(IoBase *pBase)
Initialises DMA for a specific channel.
void commandComplete()
Called by drivers when a command completes.
bool hasInterrupt()
Determines if an INTERRUPT has occurred on this channel.
MemoryRegion m_PrdTableMemRegion
bool begin(bool bWrite)
Begin a DMA operation.
physical_uintptr_t m_PrdTablePhys
PhysicalRegionDescriptor * m_PrdTable
Abstrace base class for hardware I/O capabilities.
virtual uint8_t read8(size_t offset=0)=0
virtual void write32(uint32_t value, size_t offset=0)=0
virtual void write8(uint8_t value, size_t offset=0)=0
virtual size_t size() const =0
void * virtualAddress() const
physical_uintptr_t physicalAddress() const
static const size_t continuous
static PhysicalMemoryManager & instance()
static ProcessorInformation & information()
virtual bool isMapped(void *virtualAddress)=0
virtual bool getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
static const size_t Write