usb: use io_mem on x86 via platform driver

Issue #1487
This commit is contained in:
Alexander Boettcher 2015-04-13 14:29:00 +02:00 committed by Christian Helmuth
parent a4d6be1b3d
commit 6c65e436bf
5 changed files with 103 additions and 51 deletions

View File

@ -120,6 +120,7 @@ lappend_if [have_spec gpio] boot_modules gpio_drv
build_boot_image $boot_modules
append qemu_args " -m 256 -usb -usbdevice mouse -usbdevice keyboard"
append qemu_args " -device usb-ehci,id=ehci"
run_genode_until forever

View File

@ -186,3 +186,42 @@ void platform_set_drvdata(struct platform_device *pdev, void *data)
}
/**********************
** asm-generic/io.h **
**********************/
void *_ioremap(resource_size_t phys_addr, unsigned long size, int wc)
{
dde_kit_addr_t map_addr;
if (dde_kit_request_mem(phys_addr, size, wc, &map_addr)) {
panic("Failed to request I/O memory: [%zx,%lx)", phys_addr, phys_addr + size);
return 0;
}
return (void *)map_addr;
}
void *ioremap(resource_size_t offset, unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap(struct device *dev, resource_size_t offset,
unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap_resource(struct device *dev, struct resource *res)
{
return _ioremap(res->start, res->end - res->start, 0);
}

View File

@ -2222,12 +2222,6 @@ void *devm_ioremap(struct device *dev, resource_size_t offset,
void *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
unsigned long size);
/**
* Map I/O memory write combined
*/
void *ioremap_wc(resource_size_t phys_addr, unsigned long size);
#define ioremap_nocache ioremap
void *phys_to_virt(unsigned long address);

View File

@ -682,49 +682,6 @@ void kmem_cache_free(struct kmem_cache *cache, void *objp)
** asm-generic/io.h **
**********************/
void *_ioremap(resource_size_t phys_addr, unsigned long size, int wc)
{
dde_kit_addr_t map_addr;
if (dde_kit_request_mem(phys_addr, size, wc, &map_addr)) {
PERR("Failed to request I/O memory: [%zx,%lx)", phys_addr, phys_addr + size);
return 0;
}
return (void *)map_addr;
}
void *ioremap_wc(resource_size_t phys_addr, unsigned long size)
{
return _ioremap(phys_addr, size, 1);
}
void *ioremap(resource_size_t offset, unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap(struct device *dev, resource_size_t offset,
unsigned long size)
{
return ioremap(offset, size);
}
void *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
unsigned long size)
{
return ioremap(offset, size);
}
void *devm_ioremap_resource(struct device *dev, struct resource *res)
{
return _ioremap(res->start, res->end - res->start, 0);
}
void *phys_to_virt(unsigned long address)
{
return (void *)Malloc::dma()->virt_addr(address);

View File

@ -12,12 +12,12 @@
*/
/* Genode base includes */
#include <ram_session/client.h>
#include <base/object_pool.h>
#include <io_mem_session/client.h>
#include <irq_session/connection.h>
#include <ram_session/client.h>
/* Genode os includes */
#include <os/server.h>
#include <pci_session/connection.h>
#include <pci_device/client.h>
@ -207,6 +207,29 @@ class Pci_driver : public Genode::List<Pci_driver>::Element
return Genode::Irq_session_capability();
}
static Genode::Io_mem_session_capability io_mem(resource_size_t phys) {
for (Pci_driver *d = _drivers().first(); d; d = d->next()) {
if (!d->_dev)
continue;
uint8_t bar = 0;
for (unsigned bar = 0; bar < PCI_ROM_RESOURCE; bar++) {
if ((pci_resource_flags(d->_dev, bar) & IORESOURCE_MEM) &&
(pci_resource_start(d->_dev, bar) == phys))
break;
}
if (bar >= PCI_ROM_RESOURCE)
continue;
Pci::Device_client client(d->_cap);
return client.io_mem(bar);
}
PERR("Device using i/o memory of address %zx is unknown", phys);
return Genode::Io_mem_session_capability();
}
};
/********************************
@ -443,3 +466,41 @@ Genode::Irq_session_capability platform_irq_activate(int irq)
{
return Pci_driver::irq_cap(irq);
}
/******************
** MMIO regions **
******************/
class Mem_range : public Genode::Io_mem_session_client
{
private:
Genode::Io_mem_dataspace_capability _ds;
Genode::addr_t _vaddr;
public:
Mem_range(Genode::addr_t base,
Genode::Io_mem_session_capability io_cap)
:
Io_mem_session_client(io_cap), _ds(dataspace()), _vaddr(0UL)
{
_vaddr = Genode::env()->rm_session()->attach(_ds);
_vaddr |= base & 0xfffUL;
}
Genode::addr_t vaddr() const { return _vaddr; }
};
void *ioremap(resource_size_t phys_addr, unsigned long size)
{
Mem_range * io_mem = new (Genode::env()->heap()) Mem_range(phys_addr, Pci_driver::io_mem(phys_addr));
if (io_mem->vaddr())
return (void *)io_mem->vaddr();
PERR("Failed to request I/O memory: [%zx,%lx)", phys_addr,
phys_addr + size);
return nullptr;
}