7#include "pedigree/kernel/LockGuard.h"
8#include "pedigree/kernel/panic.h"
9#include "pedigree/kernel/process/TerminationDeferral.h"
10#include "pedigree/kernel/utilities/new"
11#include "pedigree/kernel/utilities/utility.h"
14#include "modules/drivers/common/scsi/ScsiController.h"
19 : m_Disk(disk), m_Controller(
nullptr), m_Active(
false), m_Request{} {}
21 PagingStatus prepare() {
25 return PagingStatus::Busy;
26 m_Controller = m_Disk.acquirePagingController(m_ControllerUse);
28 return PagingStatus::Closed;
30 return PagingStatus::Success;
33 PagingStatus transfer(PagingOperation operation, uint64_t offset,
void* page)
override {
37 return PagingStatus::Busy;
41 return PagingStatus::Closed;
42 if (operation != PagingOperation::Flush && !page)
43 return PagingStatus::Invalid;
44 if (operation == PagingOperation::Write)
45 MemoryCopy(m_Page, page,
sizeof(m_Page));
46 m_Request = {operation, offset, m_Page, PagingStatus::Closed};
48 m_Token, 0, SCSI_REQUEST_PAGING,
reinterpret_cast<uintptr_t
>(&m_Disk),
49 reinterpret_cast<uintptr_t
>(&m_Request));
50 if (admitted != RequestQueue::PreallocatedPublishResult::Accepted)
51 return admitted == RequestQueue::PreallocatedPublishResult::TokenBusy ? PagingStatus::Busy
52 : PagingStatus::Closed;
56 panic(
"Admitted paging request could not join its completion");
57 if (m_Request.result == PagingStatus::Success && operation == PagingOperation::Read)
58 MemoryCopy(page, m_Page,
sizeof(m_Page));
59 return m_Request.result;
62 void release()
override {
67 m_Controller =
nullptr;
78 alignas(16) uint8_t m_Page[PagingChannel::PageBytes];
81void AtaDisk::preparePagingStorage() {
87void AtaDisk::releasePagingStorage() {
95 return PagingStatus::Unsupported;
98 getSize() < PagingChannel::PageBytes ||
getSize() % PagingChannel::PageBytes ||
99 (
m_pIdent.__raw[83] & 0xC000) != 0x4000 ||
100 (!
m_pIdent.data.command_sets_support.flush_cache &&
102 return PagingStatus::Unsupported;
104 return PagingStatus::NoMemory;
105 PagingStatus status = m_Paging->prepare();
106 if (status != PagingStatus::Success)
108 status = preparePagingCache(*m_Paging);
109 if (status != PagingStatus::Success) {
113 transport = m_Paging;
114 return PagingStatus::Success;
118PagingStatus AtaDisk::doPagingTransfer(PagingOperation operation, uint64_t offset,
void* page) {
120 return PagingStatus::Unsupported;
123 return PagingStatus::Unsupported;
124 if (operation == PagingOperation::Flush)
125 return doSync(SyncWholeDevice) ? PagingStatus::Success : PagingStatus::IoError;
126 if (!page || (offset % PagingChannel::PageBytes) || offset >
getSize() ||
128 return PagingStatus::Invalid;
129 constexpr uint32_t sectors = PagingChannel::PageBytes / 512;
130 const uint64_t sector = offset / 512;
132 sector > 0xffffffffffffULL - (sectors - 1))
133 return PagingStatus::Unsupported;
137 m_ControlRegs->
write8(2, 2);
139 if (status.reg.bsy || status.reg.drq)
140 return PagingStatus::IoError;
143 if (status.reg.bsy || status.reg.drq || status.reg.df || !status.reg.drdy)
144 return PagingStatus::IoError;
150 AtaPioPollBudget budget = {Time::getTicks(), 30 * Time::Multiplier::Second, 0, 30000000};
151 const bool write = operation == PagingOperation::Write;
155 write ? ataPioWrite512ByteSectors(
m_CommandRegs, m_ControlRegs,
static_cast<uint16_t*
>(page),
156 sectors, budget, status)
157 : ataPioRead512ByteSectors(
m_CommandRegs, m_ControlRegs, static_cast<uint16_t*>(page),
158 sectors, budget, status);
159 return succeeded ? PagingStatus::Success : PagingStatus::IoError;
PagingStatus preparePagingTransport(PagingTransport *&transport) override
AtaDiskType m_AtaDiskType
void setupLBA28(uint64_t n, uint32_t nSectors)
virtual size_t getNativeBlockSize() const
void setupLBA48(uint64_t n, uint32_t nSectors)
virtual size_t getSize() const
Gets the size of the disk.
virtual void write8(uint8_t value, size_t offset=0)=0
MUST_USE_RESULT bool waitForPreallocated(PreallocatedRequest &request)
bool canWaitForCompletion()
MUST_USE_RESULT PreallocatedPublishResult publishPreallocated(PreallocatedRequest &request, size_t priority, uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
virtual void write(uint64_t location)
void EXPORTED_PUBLIC panic(const char *msg) NORETURN