Skip to content

Commit

Permalink
CXHCIDevice::FreeSharedMem() implemented
Browse files Browse the repository at this point in the history
This is a prerequisite for implementing the possibility to remove
and reconnect USB devices.

class CXHCISharedMemAllocator added
  • Loading branch information
rsta2 committed Jan 26, 2020
1 parent 763042c commit 5227843
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 47 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ USB library
* CXHCIRing: Encapsulates a transfer, command or event ring for communication with the xHCI controller.
* CXHCIRootHub: Initializes the available USB root ports of the xHCI controller.
* CXHCIRootPort: Encapsulates an USB root port of the xHCI controller.
* CXHCISharedMemAllocator: Shared memory allocation for the xHCI driver.
* CXHCISlotManager: Manages the USB device slots of the xHCI controller.
* CXHCIUSBDevice: Encapsulates a single USB device, attached to the xHCI controller.

Expand Down
1 change: 1 addition & 0 deletions doc/classes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ USB library
* CXHCIRing: Encapsulates a transfer, command or event ring for communication with the xHCI controller.
* CXHCIRootHub: Initializes the available USB root ports of the xHCI controller.
* CXHCIRootPort: Encapsulates an USB root port of the xHCI controller.
* CXHCISharedMemAllocator: Shared memory allocation for the xHCI driver.
* CXHCISlotManager: Manages the USB device slots of the xHCI controller.
* CXHCIUSBDevice: Encapsulates a single USB device, attached to the xHCI controller.

Expand Down
6 changes: 3 additions & 3 deletions include/circle/usb/xhcidevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// xhcidevice.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2019 R. Stange <rsta2@o2online.de>
// Copyright (C) 2019-2020 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand All @@ -25,6 +25,7 @@
#include <circle/timer.h>
#include <circle/usb/usbrequest.h>
#include <circle/bcmpciehostbridge.h>
#include <circle/usb/xhcisharedmemallocator.h>
#include <circle/usb/xhcimmiospace.h>
#include <circle/usb/xhcislotmanager.h>
#include <circle/usb/xhcieventmanager.h>
Expand Down Expand Up @@ -70,8 +71,7 @@ class CXHCIDevice : public CUSBHostController /// USB host controller interface
private:
CBcmPCIeHostBridge m_PCIeHostBridge;

uintptr m_nSharedMemStart;
uintptr m_nSharedMemEnd;
CXHCISharedMemAllocator m_SharedMemAllocator;

CXHCIMMIOSpace *m_pMMIO;

Expand Down
73 changes: 73 additions & 0 deletions include/circle/usb/xhcisharedmemallocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// xhcisharedmemallocator.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2020 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _circle_usb_xhcisharedmemallocator_h
#define _circle_usb_xhcisharedmemallocator_h

#include <circle/types.h>

// Shared memory requirements of this xHCI driver:
//
// Size Align Boundary Count Object
// ---- ----- -------- -------------- -----------------------------------------------
// 16 64 none 1 ERST
// 248 64 4K 1 Scatchpad Buffer Array
// 264 64 4K 1 DCBAA
// 1024 64 4K <=32 Device Context
// 1024 64 64K <=2+32*EPs TRB Ring (EPs = number of endpoints per device)
// 124K 4K 4K 1 Scatchpad Buffers

// We only maintain blocks with the following specification. Other blocks, which do not
// fit these specification (blocks with smaller size/alignment/boundary requirements do
// fit), can be allocated, but are lost, if they are freed (should not happen).
#define XHCI_BLOCK_SIZE 1024
#define XHCI_BLOCK_ALIGN 64
#define XHCI_BLOCK_BOUNDARY 0x10000

struct TXHCIBlockHeader
{
u32 nMagic;
#define XHCI_BLOCK_MAGIC 0x58484349
u32 nSize;
u32 nAlign;
u32 nBoundary;
TXHCIBlockHeader *pNext;
u8 Data[0];
};

class CXHCISharedMemAllocator /// Shared memory allocation for the xHCI driver
{
public:
CXHCISharedMemAllocator (uintptr nMemStart, uintptr nMemEnd);
~CXHCISharedMemAllocator (void);

size_t GetFreeSpace (void) const;

void *Allocate (size_t nSize, size_t nAlign, size_t nBoundary);

void Free (void *pBlock);

private:
uintptr m_nMemStart;
uintptr m_nMemEnd;

TXHCIBlockHeader *m_pFreeList;
};

#endif
5 changes: 3 additions & 2 deletions lib/usb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Makefile
#
# Circle - A C++ bare metal environment for Raspberry Pi
# Copyright (C) 2014-2019 R. Stange <rsta2@o2online.de>
# Copyright (C) 2014-2020 R. Stange <rsta2@o2online.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -36,7 +36,8 @@ OBJS += dwhcidevice.o dwhciframeschednper.o dwhciframeschednsplit.o dwhciframesc
dwhciregister.o dwhcirootport.o dwhcixactqueue.o dwhcixferstagedata.o
else
OBJS += xhcicommandmanager.o xhcidevice.o xhciendpoint.o xhcieventmanager.o xhcimmiospace.o \
xhciring.o xhciroothub.o xhcirootport.o xhcislotmanager.o xhciusbdevice.o
xhciring.o xhciroothub.o xhcirootport.o xhcisharedmemallocator.o xhcislotmanager.o \
xhciusbdevice.o
endif

libusb.a: $(OBJS)
Expand Down
51 changes: 9 additions & 42 deletions lib/usb/xhcidevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// xhcidevice.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2019 R. Stange <rsta2@o2online.de>
// Copyright (C) 2019-2020 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand All @@ -29,8 +29,9 @@ static const char From[] = "xhci";

CXHCIDevice::CXHCIDevice (CInterruptSystem *pInterruptSystem, CTimer *pTimer)
: m_PCIeHostBridge (pInterruptSystem),
m_nSharedMemStart (CMemorySystem::GetCoherentPage (COHERENT_SLOT_XHCI_START)),
m_nSharedMemEnd (CMemorySystem::GetCoherentPage (COHERENT_SLOT_XHCI_END) + PAGE_SIZE - 1),
m_SharedMemAllocator (
CMemorySystem::GetCoherentPage (COHERENT_SLOT_XHCI_START),
CMemorySystem::GetCoherentPage (COHERENT_SLOT_XHCI_END) + PAGE_SIZE - 1),
m_pMMIO (0),
m_pSlotManager (0),
m_pEventManager (0),
Expand All @@ -40,8 +41,6 @@ CXHCIDevice::CXHCIDevice (CInterruptSystem *pInterruptSystem, CTimer *pTimer)
m_pRootHub (0),
m_bShutdown (FALSE)
{
assert (m_nSharedMemStart != 0);
assert (m_nSharedMemEnd != 0);
}

CXHCIDevice::~CXHCIDevice (void)
Expand Down Expand Up @@ -70,9 +69,6 @@ CXHCIDevice::~CXHCIDevice (void)

delete m_pMMIO;
m_pMMIO = 0;

m_nSharedMemStart = 0;
m_nSharedMemEnd = 0;
}

boolean CXHCIDevice::Initialize (void)
Expand Down Expand Up @@ -271,50 +267,22 @@ CXHCIRootHub *CXHCIDevice::GetRootHub (void)

void *CXHCIDevice::AllocateSharedMem (size_t nSize, size_t nAlign, size_t nBoundary)
{
assert (nSize > 0);
assert (nAlign != 0);
assert (nAlign <= nBoundary);
assert (m_nSharedMemStart != 0);
assert (m_nSharedMemEnd != 0);

size_t nAlignMask = nAlign - 1;
if (m_nSharedMemStart & nAlignMask)
{
m_nSharedMemStart += nAlignMask;
m_nSharedMemStart &= ~nAlignMask;
}

size_t nBoundaryMask = nBoundary - 1;
if ( (m_nSharedMemStart & ~nBoundaryMask)
!= ((m_nSharedMemStart + nSize-1) & ~nBoundaryMask))
{
m_nSharedMemStart += nBoundaryMask;
m_nSharedMemStart &= ~nBoundaryMask;
}

void *pResult = (void *) m_nSharedMemStart;

m_nSharedMemStart += nSize;
if (m_nSharedMemStart <= m_nSharedMemEnd)
void *pResult = m_SharedMemAllocator.Allocate (nSize, nAlign, nBoundary);
if (pResult != 0)
{
memset (pResult, 0, nSize);
}
else
{
CLogger::Get ()->Write (From, LogError, "Shared memory space exhausted");

pResult = 0;
}

return pResult;
}

void CXHCIDevice::FreeSharedMem (void *pBlock) // TODO
void CXHCIDevice::FreeSharedMem (void *pBlock)
{
#ifdef XHCI_DEBUG
CLogger::Get ()->Write (From, LogWarning,
"Trying to free shared memory at 0x%lX", (uintptr) pBlock);
#endif
m_SharedMemAllocator.Free (pBlock);
}

void CXHCIDevice::InterruptHandler (unsigned nVector)
Expand Down Expand Up @@ -390,8 +358,7 @@ void CXHCIDevice::DumpStatus (void)
m_PCIeHostBridge.DumpStatus (XHCI_PCIE_SLOT, XHCI_PCIE_FUNC);

CLogger::Get ()->Write (From, LogDebug, "%u KB shared memory free",
m_nSharedMemEnd > m_nSharedMemStart
? (m_nSharedMemEnd - m_nSharedMemStart) / 1024 : 0);
(unsigned) (m_SharedMemAllocator.GetFreeSpace () / 1024));
}

#endif
142 changes: 142 additions & 0 deletions lib/usb/xhcisharedmemallocator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//
// xhcisharedmemallocator.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2020 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <circle/usb/xhcisharedmemallocator.h>
#include <circle/logger.h>
#include <assert.h>

static const char From[] = "xhcialloc";

CXHCISharedMemAllocator::CXHCISharedMemAllocator (uintptr nMemStart, uintptr nMemEnd)
: m_nMemStart (nMemStart),
m_nMemEnd (nMemEnd),
m_pFreeList (0)
{
assert (m_nMemStart != 0);
assert (m_nMemEnd > m_nMemStart);
}

CXHCISharedMemAllocator::~CXHCISharedMemAllocator (void)
{
m_nMemStart = 0;
m_nMemEnd = 0;

m_pFreeList = 0;
}

size_t CXHCISharedMemAllocator::GetFreeSpace (void) const
{
return m_nMemEnd > m_nMemStart ? m_nMemEnd - m_nMemStart : 0;
}

void *CXHCISharedMemAllocator::Allocate (size_t nSize, size_t nAlign, size_t nBoundary)
{
assert (nSize > 0);
assert (nAlign != 0);
assert (nAlign <= nBoundary);
assert (m_nMemStart != 0);
assert (m_nMemEnd != 0);

if ( nSize <= XHCI_BLOCK_SIZE
&& nAlign <= XHCI_BLOCK_ALIGN
&& nBoundary <= XHCI_BLOCK_BOUNDARY)
{
if (m_pFreeList != 0)
{
TXHCIBlockHeader *pBlockHeader = m_pFreeList;
assert (pBlockHeader->nMagic == XHCI_BLOCK_MAGIC);
assert (pBlockHeader->nSize == XHCI_BLOCK_SIZE);
assert (pBlockHeader->nAlign == XHCI_BLOCK_ALIGN);
assert (pBlockHeader->nBoundary == XHCI_BLOCK_BOUNDARY);

m_pFreeList = pBlockHeader->pNext;
pBlockHeader->pNext = 0;

void *pResult = pBlockHeader->Data;
assert (((uintptr) pResult & (XHCI_BLOCK_ALIGN-1)) == 0);

return pResult;
}

nSize = XHCI_BLOCK_SIZE;
nAlign = XHCI_BLOCK_ALIGN;
nBoundary = XHCI_BLOCK_BOUNDARY;
}

m_nMemStart += sizeof (TXHCIBlockHeader);

size_t nAlignMask = nAlign - 1;
if (m_nMemStart & nAlignMask)
{
m_nMemStart += nAlignMask;
m_nMemStart &= ~nAlignMask;
}

size_t nBoundaryMask = nBoundary - 1;
if ( (m_nMemStart & ~nBoundaryMask)
!= ((m_nMemStart + nSize-1) & ~nBoundaryMask))
{
m_nMemStart += nBoundaryMask;
m_nMemStart &= ~nBoundaryMask;
}

TXHCIBlockHeader *pBlockHeader =
(TXHCIBlockHeader *) (m_nMemStart - sizeof (TXHCIBlockHeader));

m_nMemStart += nSize;

if (m_nMemStart > m_nMemEnd)
{
return 0;
}

pBlockHeader->nMagic = XHCI_BLOCK_MAGIC;
pBlockHeader->nSize = (u32) nSize;
pBlockHeader->nAlign = (u32) nAlign;
pBlockHeader->nBoundary = (u32) nBoundary;
pBlockHeader->pNext = 0;

void *pResult = pBlockHeader->Data;
assert (((uintptr) pResult & (XHCI_BLOCK_ALIGN-1)) == 0);

return pResult;
}

void CXHCISharedMemAllocator::Free (void *pBlock)
{
assert (pBlock != 0);

TXHCIBlockHeader *pBlockHeader =
(TXHCIBlockHeader *) ((uintptr) pBlock - sizeof (TXHCIBlockHeader));
assert (pBlockHeader->nMagic == XHCI_BLOCK_MAGIC);

if ( pBlockHeader->nSize == XHCI_BLOCK_SIZE
&& pBlockHeader->nAlign == XHCI_BLOCK_ALIGN
&& pBlockHeader->nBoundary == XHCI_BLOCK_BOUNDARY)
{
pBlockHeader->pNext = m_pFreeList;
m_pFreeList = pBlockHeader;
}
else
{
CLogger::Get ()->Write (From, LogWarning,
"Trying to free shared memory at 0x%lX (size %u, align %u)",
(uintptr) pBlock, pBlockHeader->nSize, pBlockHeader->nAlign);
}
}

0 comments on commit 5227843

Please sign in to comment.