The Pedigree Project 0.1
XhciRing.cc
1/* Copyright (c) 2026, Pedigree Developers. SPDX-License-Identifier: ISC */
2#include "XhciRing.h"
3#include "pedigree/kernel/TargetInfo.h"
4#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
5#include "pedigree/kernel/processor/VirtualAddressSpace.h"
6#include "pedigree/kernel/utilities/assert.h"
7#include "pedigree/kernel/utilities/utility.h"
8namespace XhciHw {
9bool allocate(MemoryRegion& region, size_t pages, bool contiguous) {
10 if (TargetInfo::getPageSize() != PageBytes)
11 return false;
12 if (!PhysicalMemoryManager::instance().allocateRegion(
13 region, pages,
15 VirtualAddressSpace::KernelMode | VirtualAddressSpace::Write))
16 return false;
17 ByteSet(region.virtualAddress(), 0, pages * PageBytes);
18 return true;
19}
20Ring::Ring() : m_Memory("xHCI ring"), m_Tail(0), m_Used(0), m_Cycle(true), m_Wraps(0) {}
21bool Ring::initialise() {
22 return allocate(m_Memory, 1);
23}
24bool Ring::enqueue(const Trb* entries, size_t count, uint64_t* addresses) {
25 if (!count || count > 32 || m_Used + count > RingEntries - 1)
26 return false;
27 struct Publication {
28 size_t index;
29 uint32_t control;
30 } publications[34];
31 size_t published = 0;
32 auto* ring = static_cast<volatile Trb*>(m_Memory.virtualAddress());
33 for (size_t i = 0; i < count; ++i) {
34 if (m_Tail == RingEntries - 1) {
35 const uint32_t flags = (6U << 10) | 2U | m_Cycle | (i ? entries[i - 1].control & Chain : 0);
36 ring[m_Tail].parameter = address();
37 ring[m_Tail].status = 0;
38 ring[m_Tail].control = flags ^ Cycle;
39 publications[published++] = {m_Tail, flags};
40 m_Tail = 0;
41 m_Cycle = !m_Cycle;
42 ++m_Wraps;
43 }
44 const uint32_t flags = (entries[i].control & ~Cycle) | m_Cycle;
45 ring[m_Tail].parameter = entries[i].parameter;
46 ring[m_Tail].status = entries[i].status;
47 ring[m_Tail].control = flags ^ Cycle;
48 addresses[i] = address() + m_Tail * sizeof(Trb);
49 publications[published++] = {m_Tail++, flags};
50 }
51 // Make the entire TD visible before publishing its first cycle bit.
52 FENCE();
53 while (published) {
54 const auto& publication = publications[--published];
55 ring[publication.index].control = publication.control;
56 }
57 FENCE();
58 m_Used += count;
59 return true;
60}
61void Ring::retire(size_t count) {
62 assert(count <= m_Used);
63 m_Used -= count;
64}
65} // namespace XhciHw
Special memory entity in the kernel's virtual address space.
void * virtualAddress() const
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() noexcept
Definition TargetInfo.h:40