mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
vbox6: add QEMU xHCI device-model
This commit is contained in:
parent
812c3599de
commit
1d551bd967
@ -107,6 +107,9 @@ SRC_CC += GuestHost/DragAndDrop/DnDDroppedFiles.cpp
|
||||
SRC_CC += GuestHost/DragAndDrop/DnDMIME.cpp
|
||||
SRC_CC += GuestHost/DragAndDrop/DnDPath.cpp
|
||||
|
||||
SRC_CC += devxhci.cc
|
||||
INC_DIR += $(call select_from_repositories,src/lib/libc)
|
||||
|
||||
INC_DIR += $(VBOX_DIR)/Devices/build
|
||||
INC_DIR += $(VBOX_DIR)/Devices/Bus
|
||||
INC_DIR += $(VIRTUALBOX_DIR)/include/VBox/Graphics
|
||||
@ -155,5 +158,6 @@ vboxssdt_cpuhotplug.hex: vbox-cpuhotplug.dsl
|
||||
)
|
||||
|
||||
vpath %.dsl $(VBOX_DIR)/Devices/PC
|
||||
vpath devxhci.cc $(REP_DIR)/src/virtualbox6
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
||||
|
@ -1 +1 @@
|
||||
53f753241f3d5253338f284aa833d7db04469026
|
||||
e680f42ecc53c4f0507a6e832a3e48915a6c3b2a
|
||||
|
@ -63,5 +63,7 @@ extern "C" int VBoxDevicesRegister(PPDMDEVREGCB pCallbacks, uint32_t u32Version)
|
||||
REGISTER(DeviceGIMDev);
|
||||
REGISTER(DeviceLPC);
|
||||
|
||||
REGISTER(DeviceXHCI);
|
||||
|
||||
return VINF_SUCCESS;
|
||||
}
|
||||
|
603
repos/ports/src/virtualbox6/devxhci.cc
Normal file
603
repos/ports/src/virtualbox6/devxhci.cc
Normal file
@ -0,0 +1,603 @@
|
||||
/*
|
||||
* \brief NEC XHCI device frontend
|
||||
* \author Josef Soentgen
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2015-12-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/registry.h>
|
||||
#include <libc/allocator.h>
|
||||
#include <util/list.h>
|
||||
|
||||
/* qemu-usb includes */
|
||||
#include <qemu/usb.h>
|
||||
|
||||
/* libc internal includes */
|
||||
#include <internal/thread_create.h>
|
||||
|
||||
/* Virtualbox includes */
|
||||
#define LOG_GROUP LOG_GROUP_DEV_EHCI
|
||||
#include <VBox/pci.h>
|
||||
#include <VBox/vmm/pdm.h>
|
||||
#include <VBox/vmm/pgm.h>
|
||||
#include <VBox/vmm/mm.h>
|
||||
#include <VBox/err.h>
|
||||
#include <VBox/log.h>
|
||||
#include <iprt/assert.h>
|
||||
#include <iprt/string.h>
|
||||
#include <iprt/asm.h>
|
||||
#include <iprt/asm-math.h>
|
||||
#include <iprt/semaphore.h>
|
||||
#include <iprt/critsect.h>
|
||||
#ifdef IN_RING3
|
||||
# include <iprt/alloca.h>
|
||||
# include <iprt/mem.h>
|
||||
# include <iprt/thread.h>
|
||||
# include <iprt/uuid.h>
|
||||
#endif
|
||||
#include <VBox/vusb.h>
|
||||
#include <VBoxDD.h>
|
||||
|
||||
|
||||
/* local include */
|
||||
#include "init.h"
|
||||
|
||||
|
||||
static Genode::Env *_xhci_genode_env;
|
||||
|
||||
namespace Xhci {
|
||||
|
||||
void init(Genode::Env &env)
|
||||
{
|
||||
_xhci_genode_env = &env;
|
||||
}
|
||||
} /* namespace Xhci */
|
||||
|
||||
|
||||
static bool const verbose_timer = false;
|
||||
|
||||
|
||||
/************************
|
||||
** xHCI device struct **
|
||||
************************/
|
||||
|
||||
struct Timer_queue;
|
||||
|
||||
|
||||
struct XHCI
|
||||
{
|
||||
/** Pointer to the device instance - R3 ptr. */
|
||||
PPDMDEVINSR3 pDevInsR3;
|
||||
|
||||
/** The MMIO region handle. */
|
||||
IOMMMIOHANDLE hMmio;
|
||||
|
||||
PTMTIMERR3 controller_timer;
|
||||
Timer_queue *timer_queue;
|
||||
Qemu::Controller *ctl;
|
||||
|
||||
Genode::Entrypoint *usb_ep;
|
||||
};
|
||||
|
||||
|
||||
/** Pointer to XHCI device data. */
|
||||
typedef struct XHCI *PXHCI;
|
||||
/** Read-only pointer to the XHCI device data. */
|
||||
typedef struct XHCI const *PCXHCI;
|
||||
|
||||
|
||||
/*************************************
|
||||
** Qemu::Controller helper classes **
|
||||
*************************************/
|
||||
|
||||
struct Timer_queue : public Qemu::Timer_queue
|
||||
{
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
struct Context : public Genode::List<Context>::Element
|
||||
{
|
||||
uint64_t timeout_abs_ns = ~0ULL;
|
||||
bool pending = false;
|
||||
|
||||
void *qtimer = nullptr;
|
||||
void (*cb)(void*) = nullptr;
|
||||
void *data = nullptr;
|
||||
|
||||
Context(void *qtimer, void (*cb)(void*), void *data)
|
||||
: qtimer(qtimer), cb(cb), data(data) { }
|
||||
};
|
||||
|
||||
Genode::List<Context> _context_list;
|
||||
PTMTIMER tm_timer;
|
||||
|
||||
void _append_new_context(void *qtimer, void (*cb)(void*), void *data)
|
||||
{
|
||||
Context *new_ctx = new (_alloc) Context(qtimer, cb, data);
|
||||
_context_list.insert(new_ctx);
|
||||
}
|
||||
|
||||
Context *_find_context(void const *qtimer)
|
||||
{
|
||||
for (Context *c = _context_list.first(); c; c = c->next())
|
||||
if (c->qtimer == qtimer)
|
||||
return c;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Context *_min_pending()
|
||||
{
|
||||
Context *min = nullptr;
|
||||
for (min = _context_list.first(); min; min = min->next())
|
||||
if (min && min->pending)
|
||||
break;
|
||||
|
||||
if (!min || !min->next())
|
||||
return min;
|
||||
|
||||
for (Context *c = min->next(); c; c = c->next()) {
|
||||
if ((c->timeout_abs_ns < min->timeout_abs_ns) && c->pending)
|
||||
min = c;
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
void _program_min_timer()
|
||||
{
|
||||
Context *min = _min_pending();
|
||||
if (min == nullptr) return;
|
||||
|
||||
if (TMTimerIsActive(tm_timer))
|
||||
TMTimerStop(tm_timer);
|
||||
|
||||
TMTimerSetNano(tm_timer, min->timeout_abs_ns - TMTimerGetNano(tm_timer));
|
||||
}
|
||||
|
||||
void _deactivate_timer(void *qtimer)
|
||||
{
|
||||
Context *c = _find_context(qtimer);
|
||||
if (c == nullptr) {
|
||||
Genode::error("qtimer: ", qtimer, " not found");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
if (c == _min_pending()) {
|
||||
c->pending = false;
|
||||
TMTimerStop(tm_timer);
|
||||
_program_min_timer();
|
||||
}
|
||||
|
||||
c->pending = false;
|
||||
}
|
||||
|
||||
Timer_queue(Genode::Allocator &alloc, PTMTIMER timer)
|
||||
: _alloc(alloc), tm_timer(timer) { }
|
||||
|
||||
void timeout()
|
||||
{
|
||||
uint64_t now = TMTimerGetNano(tm_timer);
|
||||
|
||||
for (Context *c = _context_list.first(); c; c = c->next()) {
|
||||
if (c->pending && c->timeout_abs_ns <= now) {
|
||||
c->pending = false;
|
||||
Qemu::usb_timer_callback(c->cb, c->data);
|
||||
}
|
||||
}
|
||||
|
||||
_program_min_timer();
|
||||
}
|
||||
|
||||
/**********************
|
||||
** TMTimer callback **
|
||||
**********************/
|
||||
|
||||
static DECLCALLBACK(void) tm_timer_cb(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
|
||||
{
|
||||
PXHCI pThis = PDMINS_2_DATA(pDevIns, PXHCI);
|
||||
Timer_queue *q = pThis->timer_queue;
|
||||
|
||||
q->timeout();
|
||||
}
|
||||
|
||||
|
||||
unsigned count_timer()
|
||||
{
|
||||
unsigned res = 0;
|
||||
|
||||
for (Context *c = _context_list.first(); c; c = c->next()) {
|
||||
if (c->pending) Genode::log("timer: ", c, " is pending");
|
||||
res++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
** Qemu::Timer_queue interface **
|
||||
*********************************/
|
||||
|
||||
Qemu::int64_t get_ns() { return TMTimerGetNano(tm_timer); }
|
||||
|
||||
Genode::Mutex _timer_mutex { };
|
||||
|
||||
void register_timer(void *qtimer, void (*cb)(void*), void *data) override
|
||||
{
|
||||
Genode::Mutex::Guard guard(_timer_mutex);
|
||||
if (verbose_timer)
|
||||
Genode::log("qtimer: ", qtimer, " cb: ", cb, " data: ", data);
|
||||
|
||||
Context *c = _find_context(qtimer);
|
||||
if (c != nullptr) {
|
||||
Genode::error("qtimer: ", qtimer, " already registred");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
_append_new_context(qtimer, cb, data);
|
||||
}
|
||||
|
||||
void delete_timer(void *qtimer) override
|
||||
{
|
||||
Genode::Mutex::Guard guard(_timer_mutex);
|
||||
if (verbose_timer)
|
||||
Genode::log("qtimer: ", qtimer);
|
||||
|
||||
Context *c = _find_context(qtimer);
|
||||
if (c == nullptr) {
|
||||
Genode::error("qtimer: ", qtimer, " not found");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
_deactivate_timer(qtimer);
|
||||
|
||||
_context_list.remove(c);
|
||||
Genode::destroy(_alloc, c);
|
||||
}
|
||||
|
||||
void activate_timer(void *qtimer, long long int expire_abs) override
|
||||
{
|
||||
Genode::Mutex::Guard guard(_timer_mutex);
|
||||
if (verbose_timer)
|
||||
Genode::log("qtimer: ", qtimer, " expire: ", expire_abs);
|
||||
|
||||
Context *c = _find_context(qtimer);
|
||||
if (c == nullptr) {
|
||||
Genode::error("qtimer: ", qtimer, " not found");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
c->timeout_abs_ns = expire_abs;
|
||||
c->pending = true;
|
||||
|
||||
_program_min_timer();
|
||||
}
|
||||
|
||||
void deactivate_timer(void *qtimer) override
|
||||
{
|
||||
Genode::Mutex::Guard guard(_timer_mutex);
|
||||
if (verbose_timer)
|
||||
Genode::log("qtimer: ", qtimer);
|
||||
|
||||
_deactivate_timer(qtimer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Pci_device : public Qemu::Pci_device
|
||||
{
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
PPDMDEVINS pci_dev;
|
||||
|
||||
struct Dma_bounce_buffer
|
||||
{
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
Qemu::addr_t const base;
|
||||
Qemu::size_t const size;
|
||||
void * const addr { _alloc.alloc(size) };
|
||||
|
||||
Dma_bounce_buffer(Genode::Allocator &alloc,
|
||||
Qemu::addr_t base,
|
||||
Qemu::size_t size)
|
||||
: _alloc { alloc }, base { base }, size { size }
|
||||
{ }
|
||||
|
||||
virtual ~Dma_bounce_buffer()
|
||||
{
|
||||
_alloc.free(addr, size);
|
||||
}
|
||||
};
|
||||
|
||||
using Reg_dma_buffer = Genode::Registered<Dma_bounce_buffer>;
|
||||
Genode::Registry<Reg_dma_buffer> _dma_buffers { };
|
||||
|
||||
Pci_device(Genode::Allocator &alloc, PPDMDEVINS pDevIns)
|
||||
: _alloc(alloc), pci_dev(pDevIns) { }
|
||||
|
||||
void raise_interrupt(int level) override {
|
||||
PDMDevHlpPCISetIrqNoWait(pci_dev, 0, level); }
|
||||
|
||||
int read_dma(Qemu::addr_t addr, void *buf, Qemu::size_t size) override {
|
||||
return PDMDevHlpPhysRead(pci_dev, addr, buf, size); }
|
||||
|
||||
int write_dma(Qemu::addr_t addr, void const *buf, Qemu::size_t size) override {
|
||||
return PDMDevHlpPhysWrite(pci_dev, addr, buf, size); }
|
||||
|
||||
void *map_dma(Qemu::addr_t base, Qemu::size_t size,
|
||||
Qemu::Pci_device::Dma_direction dir) override
|
||||
{
|
||||
Reg_dma_buffer *dma = nullptr;
|
||||
|
||||
try {
|
||||
dma = new (_alloc) Reg_dma_buffer(_dma_buffers,
|
||||
_alloc, base, size);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* copy data for write request to bounce buffer */
|
||||
if (dir == Qemu::Pci_device::Dma_direction::OUT) {
|
||||
(void)PDMDevHlpPhysRead(pci_dev, base, dma->addr, size);
|
||||
}
|
||||
|
||||
return dma->addr;
|
||||
}
|
||||
|
||||
void unmap_dma(void *addr, Qemu::size_t size,
|
||||
Qemu::Pci_device::Dma_direction dir) override
|
||||
{
|
||||
_dma_buffers.for_each([&] (Reg_dma_buffer &dma) {
|
||||
if (dma.addr != addr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy data for read request from bounce buffer */
|
||||
if (dir == Qemu::Pci_device::Dma_direction::IN) {
|
||||
(void)PDMDevHlpPhysWrite(pci_dev,
|
||||
dma.base, dma.addr, dma.size);
|
||||
}
|
||||
|
||||
Genode::destroy(_alloc, &dma);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***********************************************
|
||||
** Virtualbox Device function implementation **
|
||||
***********************************************/
|
||||
|
||||
/**
|
||||
* @callback_method_impl{FNIOMMMIOREAD}
|
||||
*/
|
||||
PDMBOTHCBDECL(VBOXSTRICTRC) xhciMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off,
|
||||
void *pv, unsigned cb)
|
||||
{
|
||||
PXHCI pThis = PDMINS_2_DATA(pDevIns, PXHCI);
|
||||
|
||||
Genode::off_t offset = off;
|
||||
Qemu::Controller *ctl = pThis->ctl;
|
||||
|
||||
ctl->mmio_read(offset, pv, cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @callback_method_impl{FNIOMMMIOWRITE}
|
||||
*/
|
||||
PDMBOTHCBDECL(VBOXSTRICTRC) xhciMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off,
|
||||
void const *pv, unsigned cb)
|
||||
{
|
||||
PXHCI pThis = PDMINS_2_DATA(pDevIns, PXHCI);
|
||||
|
||||
Genode::off_t offset = off;
|
||||
Qemu::Controller *ctl = pThis->ctl;
|
||||
|
||||
ctl->mmio_write(offset, pv, cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @interface_method_impl{PDMDEVREG,pfnReset}
|
||||
*/
|
||||
static DECLCALLBACK(void) xhciR3Reset(PPDMDEVINS pDevIns)
|
||||
{
|
||||
PXHCI pThis = PDMINS_2_DATA(pDevIns, PXHCI);
|
||||
|
||||
Qemu::usb_reset();
|
||||
Qemu::usb_update_devices();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @nterface_method_impl{PDMDEVREG,pfnDestruct}
|
||||
*/
|
||||
static DECLCALLBACK(int) xhciR3Destruct(PPDMDEVINS pDevIns)
|
||||
{
|
||||
Qemu::usb_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct Usb_ep : Genode::Entrypoint
|
||||
{
|
||||
pthread_t _pthread;
|
||||
|
||||
void _handle_pthread_registration()
|
||||
{
|
||||
Genode::Thread *myself = Genode::Thread::myself();
|
||||
if (!myself || Libc::pthread_create(&_pthread, *myself, &myself)) {
|
||||
Genode::error("USB passthough will not work - thread for "
|
||||
"pthread registration invalid");
|
||||
}
|
||||
}
|
||||
|
||||
Genode::Signal_handler<Usb_ep> _pthread_reg_sigh;
|
||||
|
||||
enum { USB_EP_STACK = 32u << 10, };
|
||||
|
||||
Usb_ep(Genode::Env &env)
|
||||
:
|
||||
Entrypoint(env, USB_EP_STACK, "usb_ep", Genode::Affinity::Location()),
|
||||
_pthread_reg_sigh(*this, *this, &Usb_ep::_handle_pthread_registration)
|
||||
{
|
||||
Genode::Signal_transmitter(_pthread_reg_sigh).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @interface_method_impl{PDMDEVREG,pfnConstruct,XHCI constructor}
|
||||
*/
|
||||
static DECLCALLBACK(int) xhciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
|
||||
{
|
||||
PXHCI pThis = PDMINS_2_DATA(pDevIns, PXHCI);
|
||||
PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
|
||||
|
||||
pThis->usb_ep = new Usb_ep(*_xhci_genode_env);
|
||||
|
||||
static Libc::Allocator alloc;
|
||||
|
||||
int rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, Timer_queue::tm_timer_cb,
|
||||
pThis, TMTIMER_FLAGS_NO_CRIT_SECT,
|
||||
"XHCI Timer", &pThis->controller_timer);
|
||||
|
||||
static Timer_queue timer_queue(alloc, pThis->controller_timer);
|
||||
pThis->timer_queue = &timer_queue;
|
||||
static Pci_device pci_device(alloc, pDevIns);
|
||||
|
||||
pThis->ctl = Qemu::usb_init(timer_queue, pci_device, *pThis->usb_ep,
|
||||
alloc, *_xhci_genode_env);
|
||||
|
||||
Qemu::Controller::Info const ctl_info = pThis->ctl->info();
|
||||
|
||||
/*
|
||||
* Init instance data.
|
||||
*/
|
||||
pThis->pDevInsR3 = pDevIns;
|
||||
|
||||
PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
|
||||
PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
|
||||
|
||||
PCIDevSetVendorId (pPciDev, ctl_info.vendor_id);
|
||||
PCIDevSetDeviceId (pPciDev, ctl_info.product_id);
|
||||
PCIDevSetClassBase (pPciDev, 0x0c); /* PCI serial */
|
||||
PCIDevSetClassSub (pPciDev, 0x03); /* USB */
|
||||
PCIDevSetClassProg (pPciDev, 0x30); /* xHCI */
|
||||
PCIDevSetInterruptPin (pPciDev, 0x01);
|
||||
PCIDevSetByte (pPciDev, 0x60, 0x30); /* Serial Bus Release Number Register */
|
||||
|
||||
/*
|
||||
* Register PCI device and I/O region.
|
||||
*/
|
||||
rc = PDMDevHlpPCIRegister(pDevIns, pPciDev);
|
||||
if (RT_FAILURE(rc))
|
||||
return rc;
|
||||
|
||||
uint32_t const mmio_flags = IOMMMIO_FLAGS_READ_DWORD
|
||||
| IOMMMIO_FLAGS_WRITE_DWORD_ZEROED;
|
||||
// | IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE;
|
||||
|
||||
rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 0, pThis->ctl->mmio_size(),
|
||||
PCI_ADDRESS_SPACE_MEM,
|
||||
xhciMmioWrite, xhciMmioRead, NULL,
|
||||
mmio_flags,
|
||||
"QEMU XHCI", &pThis->hMmio);
|
||||
if (RT_FAILURE(rc))
|
||||
return rc;
|
||||
|
||||
return VINF_SUCCESS;
|
||||
}
|
||||
|
||||
const PDMDEVREG g_DeviceXHCI =
|
||||
{
|
||||
/* .u32version = */ PDM_DEVREG_VERSION,
|
||||
/* .uReserved0 = */ 0,
|
||||
/* .szName = */ "qemu-xhci",
|
||||
/* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
|
||||
/* .fClass = */ PDM_DEVREG_CLASS_BUS_USB,
|
||||
/* .cMaxInstances = */ ~0U,
|
||||
/* .uSharedVersion = */ 42,
|
||||
/* .cbInstanceShared = */ sizeof(XHCI),
|
||||
/* .cbInstanceCC = */ 0, //sizeof(XHCICC),
|
||||
/* .cbInstanceRC = */ 0,
|
||||
/* .cMaxPciDevices = */ 1,
|
||||
/* .cMaxMsixVectors = */ 0,
|
||||
/* .pszDescription = */ "QEMU XHCI USB controller.\n",
|
||||
#if defined(IN_RING3)
|
||||
/* .pszRCMod = */ "VBoxDDRC.rc",
|
||||
/* .pszR0Mod = */ "VBoxDDR0.r0",
|
||||
/* .pfnConstruct = */ xhciR3Construct,
|
||||
/* .pfnDestruct = */ xhciR3Destruct,
|
||||
/* .pfnRelocate = */ NULL,
|
||||
/* .pfnMemSetup = */ NULL,
|
||||
/* .pfnPowerOn = */ NULL,
|
||||
/* .pfnReset = */ xhciR3Reset,
|
||||
/* .pfnSuspend = */ NULL,
|
||||
/* .pfnResume = */ NULL,
|
||||
/* .pfnAttach = */ NULL,
|
||||
/* .pfnDetach = */ NULL,
|
||||
/* .pfnQueryInterface = */ NULL,
|
||||
/* .pfnInitComplete = */ NULL,
|
||||
/* .pfnPowerOff = */ NULL,
|
||||
/* .pfnSoftReset = */ NULL,
|
||||
/* .pfnReserved0 = */ NULL,
|
||||
/* .pfnReserved1 = */ NULL,
|
||||
/* .pfnReserved2 = */ NULL,
|
||||
/* .pfnReserved3 = */ NULL,
|
||||
/* .pfnReserved4 = */ NULL,
|
||||
/* .pfnReserved5 = */ NULL,
|
||||
/* .pfnReserved6 = */ NULL,
|
||||
/* .pfnReserved7 = */ NULL,
|
||||
#elif defined(IN_RING0)
|
||||
/* .pfnEarlyConstruct = */ NULL,
|
||||
/* .pfnConstruct = */ NULL,
|
||||
/* .pfnDestruct = */ NULL,
|
||||
/* .pfnFinalDestruct = */ NULL,
|
||||
/* .pfnRequest = */ NULL,
|
||||
/* .pfnReserved0 = */ NULL,
|
||||
/* .pfnReserved1 = */ NULL,
|
||||
/* .pfnReserved2 = */ NULL,
|
||||
/* .pfnReserved3 = */ NULL,
|
||||
/* .pfnReserved4 = */ NULL,
|
||||
/* .pfnReserved5 = */ NULL,
|
||||
/* .pfnReserved6 = */ NULL,
|
||||
/* .pfnReserved7 = */ NULL,
|
||||
#elif defined(IN_RC)
|
||||
/* .pfnConstruct = */ NULL,
|
||||
/* .pfnReserved0 = */ NULL,
|
||||
/* .pfnReserved1 = */ NULL,
|
||||
/* .pfnReserved2 = */ NULL,
|
||||
/* .pfnReserved3 = */ NULL,
|
||||
/* .pfnReserved4 = */ NULL,
|
||||
/* .pfnReserved5 = */ NULL,
|
||||
/* .pfnReserved6 = */ NULL,
|
||||
/* .pfnReserved7 = */ NULL,
|
||||
#else
|
||||
# error "Not in IN_RING3, IN_RING0 or IN_RC!"
|
||||
#endif
|
||||
/* .u32VersionEnd = */ PDM_DEVREG_VERSION
|
||||
};
|
||||
|
||||
|
||||
bool use_xhci_controller()
|
||||
{
|
||||
try {
|
||||
Genode::Attached_rom_dataspace config(*_xhci_genode_env, "config");
|
||||
return config.xml().attribute_value("xhci", false);
|
||||
} catch (Genode::Rom_connection::Rom_connection_failed) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -21,4 +21,6 @@ namespace Sup { void init(Genode::Env &); }
|
||||
|
||||
namespace Network { void init(Genode::Env &); }
|
||||
|
||||
namespace Xhci { void init(Genode::Env &); }
|
||||
|
||||
#endif /* _INIT_H_ */
|
||||
|
@ -360,6 +360,7 @@ void Libc::Component::construct(Libc::Env &env)
|
||||
}
|
||||
|
||||
Sup::init(env);
|
||||
Xhci::init(env);
|
||||
|
||||
try {
|
||||
static Main main(env);
|
||||
|
35
repos/ports/src/virtualbox6/patches/qemu-xhci.patch
Normal file
35
repos/ports/src/virtualbox6/patches/qemu-xhci.patch
Normal file
@ -0,0 +1,35 @@
|
||||
--- a/src/virtualbox6/src/VBox/Main/src-client/BusAssignmentManager.cpp
|
||||
+++ b/src/virtualbox6/src/VBox/Main/src-client/BusAssignmentManager.cpp
|
||||
@@ -77,6 +77,7 @@ static const DeviceAssignmentRule aGenericRules[] =
|
||||
{"usb-ohci", 0, 6, 0, 0},
|
||||
{"usb-ehci", 0, 11, 0, 0},
|
||||
{"usb-xhci", 0, 12, 0, 0},
|
||||
+ {"qemu-xhci", 0, 29, 0, 0},
|
||||
|
||||
/* ACPI controller */
|
||||
#if 0
|
||||
diff --git a/src/VBox/Main/src-client/ConsoleImpl2.cpp b/src/VBox/Main/src-client/ConsoleImpl2.cpp
|
||||
index 9e8e481..dbb4681 100644
|
||||
--- a/src/virtualbox6/src/VBox/Main/src-client/ConsoleImpl2.cpp
|
||||
+++ a/src/virtualbox6/src/VBox/Main/src-client/ConsoleImpl2.cpp
|
||||
@@ -2135,6 +2135,20 @@ int Console::i_configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
|
||||
}
|
||||
|
||||
/*
|
||||
+ * QEMU xHCI controllers.
|
||||
+ */
|
||||
+ extern bool use_xhci_controller();
|
||||
+ if (use_xhci_controller()) {
|
||||
+
|
||||
+ InsertConfigNode(pDevices, "qemu-xhci", &pDev);
|
||||
+ InsertConfigNode(pDev, "0", &pInst);
|
||||
+ InsertConfigNode(pInst, "Config", &pCfg);
|
||||
+ InsertConfigInteger(pInst, "Trusted", 1);
|
||||
+ hrc = pBusMgr->assignPCIDevice("qemu-xhci", pInst); H();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /*
|
||||
* Storage controllers.
|
||||
*/
|
||||
com::SafeIfaceArray<IStorageController> ctrls;
|
@ -1,2 +1,3 @@
|
||||
serial.patch
|
||||
drvtap.patch
|
||||
qemu-xhci.patch
|
||||
|
@ -11,6 +11,7 @@ SRC_CC += network.cc
|
||||
LIBS += base
|
||||
LIBS += stdcxx
|
||||
LIBS += libiconv
|
||||
LIBS += qemu-usb
|
||||
|
||||
CC_OPT_main = -Wno-multistatement-macros
|
||||
CC_OPT += -DProgress=ClientProgress
|
||||
|
Loading…
Reference in New Issue
Block a user