mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-29 15:44:02 +00:00
mmio: upper-bounds checks
The classes Genode::Mmio, Genode::Register_set, Genode::Attached_mmio, and Platform::Device::Mmio now receive a template parameter 'size_t SIZE'. In each type that derives from one of these classes, it is now statically checked that the range of each Genode::Register::Register- and Genode::Register_set::Register_array-deriving sub-type is within [0..SIZE). That said, SIZE is the minimum size of the memory region provided to the above mentioned Mmio classes in order to avoid page faults or memory corruption when accessing the registers and register arrays declared inside. Note, that the range end of a register array is not the end of the last item but the end of integer access that is used for accessing the last bit in the last item. The constructors of Genode::Mmio, Genode::Attached_mmio, and Platform::Device::Mmio now receive an argument 'Byte_range_ptr range' that is expected to be the range of the backing memory region. In each type that derives from on of these classes, it is now dynamically checked that 'range.num_bytes >= SIZE', thereby implementing the above mention protection against page faults and memory corruption. The rest of the commit adapts the code throughout the Genode Labs repositories regarding the changes. Note that for that code inside Core, the commits mostly uses a simplified approach by constructing MMIO objects with range [base..base+SIZE) and not with a mapping- or specification-related range size. This should be fixed in the future. Furthermore, there are types that derive from an MMIO class but don't declare any registers or register arrays (especially with Platform::Device::Mmio). In this case SIZE is set to 0. This way, the parameters must be actively corrected by someone who later wants to add registers or register arrays, plus the places can be easily found by grep'ing for Mmio<0>. Fix #4081
This commit is contained in:
parent
ee6f5f3b1b
commit
1336b0a751
@ -218,7 +218,7 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
|
||||
void Board::Cpu::wake_up_all_cpus(void * const ip)
|
||||
{
|
||||
struct Src : Genode::Mmio
|
||||
struct Src : Genode::Mmio<0x84>
|
||||
{
|
||||
struct A7_cr0 : Register<0x4, 32>
|
||||
{
|
||||
@ -232,7 +232,7 @@ void Board::Cpu::wake_up_all_cpus(void * const ip)
|
||||
struct Gpr3 : Register<0x7c, 32> {}; /* ep core 1 */
|
||||
struct Gpr4 : Register<0x80, 32> {}; /* ep core 1 */
|
||||
|
||||
Src(void * const entry) : Genode::Mmio(SRC_MMIO_BASE)
|
||||
Src(void * const entry) : Mmio({(char *)SRC_MMIO_BASE, Mmio::SIZE})
|
||||
{
|
||||
write<Gpr3>((Gpr3::access_t)entry);
|
||||
write<Gpr4>((Gpr4::access_t)entry);
|
||||
|
@ -40,12 +40,12 @@ void Board::Cpu::wake_up_all_cpus(void * const ip)
|
||||
* read out this register and jump to it after the cpu received
|
||||
* an interrupt
|
||||
*/
|
||||
struct System_control : Genode::Mmio
|
||||
struct System_control : Genode::Mmio<0x38>
|
||||
{
|
||||
struct Flagsset : Register<0x30, 32> { };
|
||||
struct Flagsclr : Register<0x34, 32> { };
|
||||
|
||||
System_control(void * const ip) : Mmio(SYSTEM_CONTROL_MMIO_BASE)
|
||||
System_control(void * const ip) : Mmio({(char *)SYSTEM_CONTROL_MMIO_BASE, Mmio::SIZE})
|
||||
{
|
||||
write<Flagsclr>(~0UL);
|
||||
write<Flagsset>(reinterpret_cast<Flagsset::access_t>(ip));
|
||||
|
@ -52,7 +52,7 @@ class Cpu_counter
|
||||
};
|
||||
|
||||
|
||||
struct Scu : Genode::Mmio
|
||||
struct Scu : Genode::Mmio<0x34>
|
||||
{
|
||||
struct Cr : Register<0x0, 32>
|
||||
{
|
||||
@ -72,7 +72,7 @@ struct Scu : Genode::Mmio
|
||||
struct Cpu3_way : Bitfield<12, 4> { };
|
||||
};
|
||||
|
||||
Scu() : Genode::Mmio(Board::Cpu_mmio::SCU_MMIO_BASE) { }
|
||||
Scu() : Mmio({(char *)Board::Cpu_mmio::SCU_MMIO_BASE, Mmio::SIZE}) { }
|
||||
|
||||
void invalidate()
|
||||
{
|
||||
|
@ -15,10 +15,14 @@
|
||||
|
||||
Hw::Pic::Pic()
|
||||
:
|
||||
_distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE),
|
||||
_redistr(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE),
|
||||
_redistr_sgi(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE +
|
||||
Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE / 2),
|
||||
_distr({(char *)Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE,
|
||||
Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE}),
|
||||
_redistr({(char *)Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE,
|
||||
Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE}),
|
||||
_redistr_sgi({(char *)Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE +
|
||||
Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE / 2,
|
||||
Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE -
|
||||
Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE / 2}),
|
||||
_max_irq(_distr.max_irq())
|
||||
{
|
||||
/* disable device */
|
||||
|
@ -29,7 +29,7 @@ namespace Bootstrap {
|
||||
}
|
||||
|
||||
|
||||
class Bootstrap::Aipstz : public Genode::Mmio
|
||||
class Bootstrap::Aipstz : public Genode::Mmio<0x54>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -66,7 +66,7 @@ class Bootstrap::Aipstz : public Genode::Mmio
|
||||
/**
|
||||
* Configure this module appropriately for the first kernel run
|
||||
*/
|
||||
Aipstz(Genode::addr_t const base) : Genode::Mmio(base)
|
||||
Aipstz(Genode::addr_t const base) : Mmio({(char *)base, Mmio::SIZE})
|
||||
{
|
||||
/* avoid AIPS intervention at any memory access */
|
||||
write<Mpr1>(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED);
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace Bootstrap { struct Csu; }
|
||||
|
||||
|
||||
struct Bootstrap::Csu : Genode::Mmio
|
||||
struct Bootstrap::Csu : Genode::Mmio<0x36c>
|
||||
{
|
||||
template <Genode::off_t OFF>
|
||||
struct Csl : public Register<OFF, 32>
|
||||
@ -99,7 +99,7 @@ struct Bootstrap::Csu : Genode::Mmio
|
||||
bool secure_uart,
|
||||
bool secure_gpio,
|
||||
bool secure_esdhc,
|
||||
bool secure_i2c) : Genode::Mmio(base)
|
||||
bool secure_i2c) : Mmio({(char *)base, Mmio::SIZE})
|
||||
{
|
||||
/* Power (CCM, SRC, DPLLIP1-4, GPC and OWIRE) */
|
||||
write<Csl09::Slave_a>(Csl00::UNSECURE);
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
Hw::Pic::Pic()
|
||||
:
|
||||
Genode::Mmio(Board::IRQ_CONTROLLER_BASE)
|
||||
Mmio({(char *)Board::IRQ_CONTROLLER_BASE, Board::IRQ_CONTROLLER_SIZE})
|
||||
{
|
||||
for (unsigned i = 0; i < NR_OF_IRQ; i++) {
|
||||
write<Intsec::Nonsecure>(!Board::secure_irq(i), i);
|
||||
|
@ -21,7 +21,7 @@
|
||||
namespace Genode { class Multiboot_info; }
|
||||
|
||||
|
||||
class Genode::Multiboot_info : Mmio
|
||||
class Genode::Multiboot_info : Mmio<0x34>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -39,17 +39,17 @@ class Genode::Multiboot_info : Mmio
|
||||
MAGIC = 0x2badb002,
|
||||
};
|
||||
|
||||
Multiboot_info(addr_t mbi) : Mmio(mbi) { }
|
||||
Multiboot_info(addr_t mbi) : Mmio({(char *)mbi, Mmio::SIZE}) { }
|
||||
Multiboot_info(addr_t mbi, bool strip);
|
||||
|
||||
struct Mmap : Genode::Mmio
|
||||
struct Mmap : Genode::Mmio<0x1c>
|
||||
{
|
||||
struct Size : Register <0x00, 32> { };
|
||||
struct Addr : Register <0x04, 64> { };
|
||||
struct Length : Register <0x0c, 64> { };
|
||||
struct Type : Register <0x14, 8> { enum { MEMORY = 1 }; };
|
||||
|
||||
Mmap(addr_t mmap = 0) : Mmio(mmap) { }
|
||||
Mmap(addr_t mmap = 0) : Mmio({(char *)mmap, Mmio::SIZE}) { }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -19,13 +19,14 @@
|
||||
|
||||
namespace Genode { class Multiboot2_info; }
|
||||
|
||||
class Genode::Multiboot2_info : Mmio
|
||||
class Genode::Multiboot2_info : Mmio<0x8>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Size : Register <0x0, 32> { };
|
||||
|
||||
struct Tag : Genode::Mmio
|
||||
template <size_t SIZE>
|
||||
struct Tag_tpl : Genode::Mmio<SIZE>
|
||||
{
|
||||
enum { LOG2_SIZE = 3 };
|
||||
|
||||
@ -42,21 +43,23 @@ class Genode::Multiboot2_info : Mmio
|
||||
};
|
||||
struct Size : Register <0x04, 32> { };
|
||||
|
||||
Tag(addr_t addr) : Mmio(addr) { }
|
||||
Tag_tpl(addr_t addr) : Mmio<SIZE>({(char *)addr, SIZE}) { }
|
||||
};
|
||||
|
||||
struct Efi_system_table_64 : Tag
|
||||
using Tag = Tag_tpl<0x8>;
|
||||
|
||||
struct Efi_system_table_64 : Tag_tpl<0x10>
|
||||
{
|
||||
struct Pointer : Register <0x08, 64> { };
|
||||
|
||||
Efi_system_table_64(addr_t addr) : Tag(addr) { }
|
||||
Efi_system_table_64(addr_t addr) : Tag_tpl(addr) { }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
enum { MAGIC = 0x36d76289UL };
|
||||
|
||||
struct Memory : Genode::Mmio
|
||||
struct Memory : Genode::Mmio<0x14>
|
||||
{
|
||||
enum { SIZE = 3 * 8 };
|
||||
|
||||
@ -64,10 +67,10 @@ class Genode::Multiboot2_info : Mmio
|
||||
struct Size : Register <0x08, 64> { };
|
||||
struct Type : Register <0x10, 32> { enum { MEMORY = 1 }; };
|
||||
|
||||
Memory(addr_t mmap = 0) : Mmio(mmap) { }
|
||||
Memory(addr_t mmap = 0) : Mmio({(char *)mmap, Mmio::SIZE}) { }
|
||||
};
|
||||
|
||||
Multiboot2_info(addr_t mbi) : Mmio(mbi) { }
|
||||
Multiboot2_info(addr_t mbi) : Mmio({(char *)mbi, Mmio::SIZE}) { }
|
||||
|
||||
template <typename FUNC_MEM,
|
||||
typename FUNC_ACPI,
|
||||
|
@ -272,7 +272,7 @@ Bootstrap::Platform::Board::Board()
|
||||
}
|
||||
|
||||
|
||||
struct Lapic : Mmio
|
||||
struct Lapic : Mmio<Hw::Cpu_memory_map::LAPIC_SIZE>
|
||||
{
|
||||
struct Svr : Register<0x0f0, 32>
|
||||
{
|
||||
@ -299,7 +299,7 @@ struct Lapic : Mmio
|
||||
struct Destination : Bitfield<24, 8> { };
|
||||
};
|
||||
|
||||
Lapic(addr_t const addr) : Mmio(addr) { }
|
||||
Lapic(addr_t const addr) : Mmio({(char *)addr, Mmio::SIZE}) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ enum {
|
||||
|
||||
Board::Timer::Timer(unsigned cpu_id)
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Board::Cpu_mmio::GLOBAL_TIMER_MMIO_BASE))
|
||||
Mmio({(char *)Platform::mmio_to_virt(Board::Cpu_mmio::GLOBAL_TIMER_MMIO_BASE), Mmio::SIZE})
|
||||
{
|
||||
enum { PRESCALER = Board::CORTEX_A9_GLOBAL_TIMER_DIV - 1 };
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace Board { class Timer; }
|
||||
/**
|
||||
* Timer driver for core
|
||||
*/
|
||||
struct Board::Timer : Genode::Mmio
|
||||
struct Board::Timer : Genode::Mmio<0x18>
|
||||
{
|
||||
/**
|
||||
* Counter value registers
|
||||
|
@ -27,9 +27,9 @@ static inline addr_t redistributor_addr()
|
||||
|
||||
Hw::Pic::Pic()
|
||||
:
|
||||
_distr(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE)),
|
||||
_redistr(redistributor_addr()),
|
||||
_redistr_sgi(redistributor_addr() + 0x10000),
|
||||
_distr({(char *)Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE), Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE}),
|
||||
_redistr({(char *)redistributor_addr(), Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE}),
|
||||
_redistr_sgi({(char *)redistributor_addr() + 0x10000, Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE - 0x10000}),
|
||||
_max_irq(_distr.max_irq())
|
||||
{
|
||||
_redistributor_init();
|
||||
|
@ -28,7 +28,7 @@ unsigned Timer::interrupt_id() const { return Board::EPIT_1_IRQ; }
|
||||
|
||||
Board::Timer::Timer(unsigned)
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Board::EPIT_1_MMIO_BASE))
|
||||
Mmio({(char *)Platform::mmio_to_virt(Board::EPIT_1_MMIO_BASE), Mmio::SIZE})
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace Board { class Timer; }
|
||||
/**
|
||||
* Timer driver for core
|
||||
*/
|
||||
struct Board::Timer : Genode::Mmio
|
||||
struct Board::Timer : Genode::Mmio<0x14>
|
||||
{
|
||||
enum { TICS_PER_MS = 33333 };
|
||||
|
||||
|
@ -18,4 +18,4 @@
|
||||
using namespace Core;
|
||||
|
||||
|
||||
Hw::Pic::Pic() : Mmio(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE)) { }
|
||||
Hw::Pic::Pic() : Mmio({(char *)Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE), Mmio::SIZE}) { }
|
||||
|
@ -23,7 +23,7 @@ using Board::Pic;
|
||||
|
||||
Pic::Gich::Gich()
|
||||
:
|
||||
Genode::Mmio(Core::Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_VT_CTRL_BASE))
|
||||
Mmio({(char *)Core::Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_VT_CTRL_BASE), Mmio::SIZE})
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ class Board::Pic : public Hw::Gicv2
|
||||
|
||||
using uint32_t = Genode::uint32_t;
|
||||
|
||||
struct Gich : Genode::Mmio
|
||||
struct Gich : Genode::Mmio<0x104>
|
||||
{
|
||||
struct Gich_hcr : Register<0x00, 32> { };
|
||||
struct Gich_vmcr : Register<0x08, 32> { };
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
Board::Pic::Pic(Global_interrupt_controller &)
|
||||
:
|
||||
_plic(Core::Platform::mmio_to_virt(Board::PLIC_BASE))
|
||||
_plic({(char *)Core::Platform::mmio_to_virt(Board::PLIC_BASE), Board::PLIC_SIZE})
|
||||
{
|
||||
/* enable external interrupts */
|
||||
enum { SEIE = 0x200 };
|
||||
|
@ -35,14 +35,14 @@ class Genode::Fpu_context
|
||||
*/
|
||||
char _fxsave_area[527];
|
||||
|
||||
struct Context : Mmio
|
||||
struct Context : Mmio<512>
|
||||
{
|
||||
struct Fcw : Register<0, 16> { };
|
||||
struct Mxcsr : Register<24, 32> { };
|
||||
|
||||
Context(addr_t const base) : Mmio(base)
|
||||
Context(addr_t const base) : Mmio({(char *)base, Mmio::SIZE})
|
||||
{
|
||||
memset((void *)base, 0, 512);
|
||||
memset((void *)base, 0, Mmio::SIZE);
|
||||
write<Fcw>(0x37f); /* mask exceptions SysV ABI */
|
||||
write<Mxcsr>(0x1f80);
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <irq_session/irq_session.h>
|
||||
#include <hw/spec/x86_64/x86_64.h>
|
||||
|
||||
/* core includes */
|
||||
#include <port_io.h>
|
||||
@ -40,7 +39,7 @@ enum {
|
||||
Local_interrupt_controller::
|
||||
Local_interrupt_controller(Global_interrupt_controller &global_irq_ctrl)
|
||||
:
|
||||
Mmio { Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()) },
|
||||
Mmio { {(char *)Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()), Mmio::SIZE} },
|
||||
_global_irq_ctrl { global_irq_ctrl }
|
||||
{
|
||||
init();
|
||||
@ -236,7 +235,7 @@ Global_interrupt_controller::_create_irt_entry(unsigned const irq)
|
||||
|
||||
Global_interrupt_controller::Global_interrupt_controller()
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_IOAPIC_BASE))
|
||||
Mmio({(char *)Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_IOAPIC_BASE), Mmio::SIZE})
|
||||
{
|
||||
write<Ioregsel>(IOAPICVER);
|
||||
_irte_count = read<Iowin::Maximum_redirection_entry>() + 1;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
#include <hw/spec/x86_64/x86_64.h>
|
||||
|
||||
namespace Board {
|
||||
|
||||
@ -47,7 +48,7 @@ struct Board::Irte : Genode::Register<64>
|
||||
};
|
||||
|
||||
|
||||
class Board::Global_interrupt_controller : public Genode::Mmio
|
||||
class Board::Global_interrupt_controller : public Genode::Mmio<Hw::Cpu_memory_map::MMIO_IOAPIC_SIZE>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -147,7 +148,7 @@ class Board::Global_interrupt_controller : public Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
class Board::Local_interrupt_controller : public Genode::Mmio
|
||||
class Board::Local_interrupt_controller : public Genode::Mmio<Hw::Cpu_memory_map::LAPIC_SIZE>
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -55,7 +55,7 @@ uint32_t Board::Timer::pit_calc_timer_freq(void)
|
||||
|
||||
Board::Timer::Timer(unsigned)
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()))
|
||||
Mmio({(char *)Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()), Mmio::SIZE})
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ namespace Board { class Timer; }
|
||||
/**
|
||||
* LAPIC-based timer driver for core
|
||||
*/
|
||||
struct Board::Timer: Genode::Mmio
|
||||
struct Board::Timer: Genode::Mmio<Hw::Cpu_memory_map::LAPIC_SIZE>
|
||||
{
|
||||
enum {
|
||||
/* PIT constants */
|
||||
|
@ -26,7 +26,7 @@ using Board::Vmcb;
|
||||
|
||||
Vmcb::Vmcb(Genode::uint32_t id)
|
||||
:
|
||||
Mmio((Genode::addr_t)this)
|
||||
Mmio({(char *)this, Mmio::SIZE})
|
||||
{
|
||||
write<Guest_asid>(id);
|
||||
write<Msrpm_base_pa>(dummy_msrpm());
|
||||
|
@ -77,11 +77,10 @@ struct Board::Vmcb_control_area
|
||||
struct Board::Vmcb_reserved_for_host
|
||||
{
|
||||
/* 64bit used by the inherited Mmio class here */
|
||||
Genode::uint64_t _reserved[1];
|
||||
Genode::addr_t root_vmcb_phys = 0U;
|
||||
};
|
||||
static_assert(Board::Vmcb_control_area::total_size -
|
||||
sizeof(Board::Vmcb_control_area) - sizeof(Genode::Mmio) -
|
||||
sizeof(Board::Vmcb_control_area) - sizeof(Genode::Mmio<0>) -
|
||||
sizeof(Board::Vmcb_reserved_for_host) ==
|
||||
0);
|
||||
|
||||
@ -136,7 +135,7 @@ struct Board::Vmcb_state_save_area
|
||||
struct alignas(Genode::get_page_size()) Board::Vmcb
|
||||
:
|
||||
Board::Vmcb_control_area,
|
||||
public Genode::Mmio,
|
||||
public Genode::Mmio<Genode::get_page_size()>,
|
||||
Board::Vmcb_reserved_for_host,
|
||||
Board::Vmcb_state_save_area
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ class Hw::Gicv2
|
||||
/**
|
||||
* Distributor of the ARM generic interrupt controller
|
||||
*/
|
||||
struct Distributor : Genode::Mmio
|
||||
struct Distributor : Genode::Mmio<0xf04>
|
||||
{
|
||||
static constexpr unsigned nr_of_irq = 1024;
|
||||
|
||||
@ -99,7 +99,7 @@ class Hw::Gicv2
|
||||
};
|
||||
};
|
||||
|
||||
Distributor(Genode::addr_t const base) : Genode::Mmio(base) { }
|
||||
Distributor(Genode::addr_t const base) : Mmio({(char *)base, Mmio::SIZE}) { }
|
||||
|
||||
/**
|
||||
* Return minimum IRQ priority
|
||||
@ -125,7 +125,7 @@ class Hw::Gicv2
|
||||
/**
|
||||
* CPU interface of the ARM generic interrupt controller
|
||||
*/
|
||||
struct Cpu_interface : Genode::Mmio
|
||||
struct Cpu_interface : Genode::Mmio<0x14>
|
||||
{
|
||||
/**
|
||||
* Control register
|
||||
@ -162,7 +162,7 @@ class Hw::Gicv2
|
||||
struct Eoir : Register<0x10, 32, true> {
|
||||
struct Irq_id : Bitfield<0,10> { }; };
|
||||
|
||||
Cpu_interface(Genode::addr_t const base) : Genode::Mmio(base) { }
|
||||
Cpu_interface(Genode::addr_t const base) : Mmio({(char *)base, Mmio::SIZE}) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ class Hw::Pic
|
||||
static constexpr unsigned min_spi = 32;
|
||||
static constexpr unsigned spurious_id = 1023;
|
||||
|
||||
struct Distributor : Genode::Mmio
|
||||
struct Distributor : Genode::Mmio<0x7fe0>
|
||||
{
|
||||
static constexpr unsigned nr_of_irq = 1024;
|
||||
|
||||
@ -103,19 +103,17 @@ class Hw::Pic
|
||||
|
||||
unsigned max_irq() { return 32 * (read<Typer::It_lines_number>() + 1) - 1; }
|
||||
|
||||
Distributor(Genode::addr_t const base) : Genode::Mmio(base)
|
||||
{ }
|
||||
using Mmio::Mmio;
|
||||
};
|
||||
|
||||
struct Redistributor : Genode::Mmio
|
||||
struct Redistributor : Genode::Mmio<0x4>
|
||||
{
|
||||
struct Ctlr : Register<0x0, 32>
|
||||
{
|
||||
struct Uwp : Bitfield<31, 1> { };
|
||||
};
|
||||
|
||||
Redistributor(Genode::addr_t const base) : Genode::Mmio(base)
|
||||
{ }
|
||||
using Mmio::Mmio;
|
||||
|
||||
/* wait for upstream writes */
|
||||
void wait_for_uwp()
|
||||
@ -126,7 +124,7 @@ class Hw::Pic
|
||||
}
|
||||
};
|
||||
|
||||
struct Redistributor_sgi_ppi : Genode::Mmio
|
||||
struct Redistributor_sgi_ppi : Genode::Mmio<0xc08>
|
||||
{
|
||||
struct Igroupr0 : Register<0x80, 32> { };
|
||||
|
||||
@ -143,8 +141,7 @@ class Hw::Pic
|
||||
|
||||
struct Icfgr1 : Register<0xc04, 32> { };
|
||||
|
||||
Redistributor_sgi_ppi(Genode::addr_t const base) : Genode::Mmio(base)
|
||||
{ }
|
||||
using Mmio::Mmio;
|
||||
};
|
||||
|
||||
struct Cpu_interface
|
||||
|
@ -19,7 +19,7 @@
|
||||
namespace Hw { class Pic; }
|
||||
|
||||
|
||||
class Hw::Pic : public Genode::Mmio
|
||||
class Hw::Pic : public Genode::Mmio<0xf04>
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
namespace Hw { struct Pl310; }
|
||||
|
||||
|
||||
class Hw::Pl310 : public Genode::Mmio
|
||||
class Hw::Pl310 : public Genode::Mmio<0xf64>
|
||||
{
|
||||
protected:
|
||||
|
||||
@ -104,7 +104,7 @@ class Hw::Pl310 : public Genode::Mmio
|
||||
|
||||
public:
|
||||
|
||||
Pl310(Genode::addr_t const base) : Mmio(base) { }
|
||||
Pl310(Genode::addr_t const base) : Mmio({(char *)base, Mmio::SIZE}) { }
|
||||
|
||||
void enable() {}
|
||||
void disable() {}
|
||||
|
@ -59,20 +59,20 @@ struct Hw::Apic_madt
|
||||
|
||||
Apic_madt *next() const { return reinterpret_cast<Apic_madt *>((Genode::uint8_t *)this + length); }
|
||||
|
||||
struct Ioapic : Genode::Mmio
|
||||
struct Ioapic : Genode::Mmio<0xc>
|
||||
{
|
||||
struct Id : Register <0x02, 8> { };
|
||||
struct Paddr : Register <0x04, 32> { };
|
||||
struct Gsi_base : Register <0x08, 32> { };
|
||||
|
||||
Ioapic(Apic_madt const * a) : Mmio(reinterpret_cast<Genode::addr_t>(a)) { }
|
||||
Ioapic(Apic_madt const * a) : Mmio({(char *)a, Mmio::SIZE}) { }
|
||||
};
|
||||
|
||||
struct Lapic : Genode::Mmio
|
||||
struct Lapic : Genode::Mmio<0x8>
|
||||
{
|
||||
struct Flags : Register <0x04, 32> { enum { VALID = 1 }; };
|
||||
|
||||
Lapic(Apic_madt const * a) : Mmio(reinterpret_cast<Genode::addr_t>(a)) { }
|
||||
Lapic(Apic_madt const * a) : Mmio({(char *)a, Mmio::SIZE}) { }
|
||||
|
||||
bool valid() { return read<Flags>() & Flags::VALID; };
|
||||
};
|
||||
@ -81,7 +81,7 @@ struct Hw::Apic_madt
|
||||
|
||||
|
||||
/* ACPI spec 5.2.9 and ACPI GAS 5.2.3.2 */
|
||||
struct Hw::Acpi_fadt : Genode::Mmio
|
||||
struct Hw::Acpi_fadt : Genode::Mmio<276>
|
||||
{
|
||||
enum Addressspace { IO = 0x1 };
|
||||
|
||||
@ -174,7 +174,7 @@ struct Hw::Acpi_fadt : Genode::Mmio
|
||||
asm volatile ("outl %0, %w1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
Acpi_fadt(Acpi_generic const * a) : Mmio(Genode::addr_t(a)) { }
|
||||
Acpi_fadt(Acpi_generic const * a) : Mmio({(char *)a, Mmio::SIZE}) { }
|
||||
|
||||
addr_t facs() const
|
||||
{
|
||||
@ -346,7 +346,7 @@ struct Hw::Acpi_fadt : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Hw::Acpi_facs : Genode::Mmio
|
||||
struct Hw::Acpi_facs : Genode::Mmio<64>
|
||||
{
|
||||
struct Length : Register < 0x04, 32> { };
|
||||
struct Fw_wake_vector : Register < 0x0c, 32> { };
|
||||
@ -362,7 +362,7 @@ struct Hw::Acpi_facs : Genode::Mmio
|
||||
write<Fw_wake_vector_ext>(0);
|
||||
}
|
||||
|
||||
Acpi_facs(addr_t const mmio) : Mmio(mmio) { }
|
||||
Acpi_facs(addr_t const mmio) : Mmio({(char *)mmio, Mmio::SIZE}) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@ struct Hw::Cpu_memory_map
|
||||
enum {
|
||||
MMIO_IOAPIC_BASE = 0xfec00000,
|
||||
MMIO_IOAPIC_SIZE = 0x1000,
|
||||
LAPIC_SIZE = 0xe34,
|
||||
};
|
||||
|
||||
static Genode::addr_t lapic_phys_base()
|
||||
|
@ -24,7 +24,7 @@ namespace Genode { class Imx_uart; }
|
||||
/**
|
||||
* Driver base for i.MX UART-module
|
||||
*/
|
||||
class Genode::Imx_uart: Mmio
|
||||
class Genode::Imx_uart: Mmio<0xa2>
|
||||
{
|
||||
/**
|
||||
* Control register 1
|
||||
@ -246,7 +246,7 @@ class Genode::Imx_uart: Mmio
|
||||
*
|
||||
* \param base device MMIO base
|
||||
*/
|
||||
Imx_uart(addr_t base, uint32_t, uint32_t) : Mmio(base)
|
||||
Imx_uart(addr_t base, uint32_t, uint32_t) : Mmio({(char*)base, Mmio::SIZE})
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
@ -17,13 +17,13 @@
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Genode { class Pl011_uart; }
|
||||
namespace Genode { class Pl011_uart; }
|
||||
|
||||
|
||||
/**
|
||||
* Driver base for the PrimeCell UART PL011 Revision r1p3
|
||||
*/
|
||||
class Genode::Pl011_uart : Mmio
|
||||
class Genode::Pl011_uart : Mmio<0x3a>
|
||||
{
|
||||
protected:
|
||||
|
||||
@ -132,7 +132,7 @@ class Genode::Pl011_uart : Mmio
|
||||
|
||||
|
||||
Genode::Pl011_uart::Pl011_uart(addr_t const base, uint32_t const clock,
|
||||
uint32_t const baud_rate) : Mmio(base)
|
||||
uint32_t const baud_rate) : Mmio({(char *)base, Mmio::SIZE})
|
||||
{
|
||||
write<Uartcr>(Uartcr::Uarten::bits(1) |
|
||||
Uartcr::Txe::bits(1) |
|
||||
|
@ -22,21 +22,21 @@
|
||||
|
||||
namespace Genode { class Bios_data_area; }
|
||||
|
||||
class Genode::Bios_data_area : Mmio
|
||||
class Genode::Bios_data_area : Mmio<0x12>
|
||||
{
|
||||
friend Unmanaged_singleton_constructor;
|
||||
|
||||
private:
|
||||
|
||||
struct Serial_base_com1 : Register<0x400, 16> { };
|
||||
struct Equipment : Register<0x410, 16>
|
||||
struct Serial_base_com1 : Register<0x0, 16> { };
|
||||
struct Equipment : Register<0x10, 16>
|
||||
{
|
||||
struct Serial_count : Bitfield<9, 3> { };
|
||||
};
|
||||
|
||||
static addr_t _mmio_base_virt();
|
||||
|
||||
Bios_data_area() : Mmio(_mmio_base_virt()) { }
|
||||
Bios_data_area() : Mmio({(char *)(_mmio_base_virt() + 0x400), Mmio::SIZE}) { }
|
||||
|
||||
public:
|
||||
|
||||
|
@ -15,12 +15,14 @@
|
||||
#define _INCLUDE__UTIL__MMIO_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
#include <util/string.h>
|
||||
#include <util/register_set.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Mmio_plain_access;
|
||||
class Mmio;
|
||||
template <size_t> class Mmio;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,27 +34,24 @@ class Genode::Mmio_plain_access
|
||||
|
||||
private:
|
||||
|
||||
addr_t const _base;
|
||||
Byte_range_ptr const _range;
|
||||
|
||||
/**
|
||||
* Write '_ACCESS_T' typed 'value' to MMIO base + 'offset'
|
||||
* Write 'ACCESS_T' typed 'value' to MMIO base + 'offset'
|
||||
*/
|
||||
template <typename ACCESS_T>
|
||||
inline void _write(off_t const offset, ACCESS_T const value)
|
||||
{
|
||||
addr_t const dst = _base + offset;
|
||||
*(ACCESS_T volatile *)dst = value;
|
||||
*(ACCESS_T volatile *)(_range.start + offset) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read '_ACCESS_T' typed from MMIO base + 'offset'
|
||||
* Read 'ACCESS_T' typed from MMIO base + 'offset'
|
||||
*/
|
||||
template <typename ACCESS_T>
|
||||
inline ACCESS_T _read(off_t const &offset) const
|
||||
{
|
||||
addr_t const dst = _base + offset;
|
||||
ACCESS_T const value = *(ACCESS_T volatile *)dst;
|
||||
return value;
|
||||
return *(ACCESS_T volatile *)(_range.start + offset);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -62,9 +61,16 @@ class Genode::Mmio_plain_access
|
||||
*
|
||||
* \param base base address of targeted MMIO region
|
||||
*/
|
||||
Mmio_plain_access(addr_t const base) : _base(base) { }
|
||||
Mmio_plain_access(Byte_range_ptr const &range) : _range(range.start, range.num_bytes) { }
|
||||
|
||||
addr_t base() const { return _base; }
|
||||
Byte_range_ptr range_at(off_t offset) const
|
||||
{
|
||||
return {_range.start + offset, _range.num_bytes - offset};
|
||||
}
|
||||
|
||||
Byte_range_ptr range() const { return range_at(0); }
|
||||
|
||||
addr_t base() const { return (addr_t)range().start; }
|
||||
};
|
||||
|
||||
|
||||
@ -73,17 +79,28 @@ class Genode::Mmio_plain_access
|
||||
*
|
||||
* For further details refer to the documentation of the 'Register_set' class.
|
||||
*/
|
||||
struct Genode::Mmio : Mmio_plain_access, Register_set<Mmio_plain_access>
|
||||
template <Genode::size_t MMIO_SIZE>
|
||||
struct Genode::Mmio : Mmio_plain_access, Register_set<Mmio_plain_access, MMIO_SIZE>
|
||||
{
|
||||
static constexpr size_t SIZE = MMIO_SIZE;
|
||||
|
||||
class Range_violation : Exception { };
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param base base address of targeted MMIO region
|
||||
* \param range byte range of targeted MMIO region
|
||||
*/
|
||||
Mmio(addr_t const base)
|
||||
Mmio(Byte_range_ptr const &range)
|
||||
:
|
||||
Mmio_plain_access(base),
|
||||
Register_set(*static_cast<Mmio_plain_access *>(this)) { }
|
||||
Mmio_plain_access(range),
|
||||
Register_set<Mmio_plain_access, SIZE>(*static_cast<Mmio_plain_access *>(this))
|
||||
{
|
||||
if (range.num_bytes < SIZE) {
|
||||
error("MMIO range is unexpectedly too small");
|
||||
throw Range_violation { };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__UTIL__MMIO_H_ */
|
||||
|
@ -23,7 +23,8 @@
|
||||
namespace Genode {
|
||||
|
||||
struct Register_set_plain_access;
|
||||
template <typename> class Register_set;
|
||||
struct Register_set_base;
|
||||
template <typename, size_t> class Register_set;
|
||||
}
|
||||
|
||||
|
||||
@ -68,6 +69,21 @@ struct Genode::Register_set_plain_access
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Register_set_base : Noncopyable
|
||||
{
|
||||
/**
|
||||
* Interface for delaying the execution of a calling thread
|
||||
*/
|
||||
struct Delayer : Interface
|
||||
{
|
||||
/**
|
||||
* Delay execution of the caller for 'us' microseconds
|
||||
*/
|
||||
virtual void usleep(uint64_t us) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set of fine-grained and typesafe accessible registers with offsets
|
||||
*
|
||||
@ -83,8 +99,8 @@ struct Genode::Register_set_plain_access
|
||||
* must not define members named 'Register_base', 'Bitfield_base',
|
||||
* 'Register_array_base' or 'Array_bitfield_base'.
|
||||
*/
|
||||
template <typename PLAIN_ACCESS>
|
||||
class Genode::Register_set : Noncopyable
|
||||
template <typename PLAIN_ACCESS, Genode::size_t REGISTER_SET_SIZE>
|
||||
class Genode::Register_set : public Register_set_base
|
||||
{
|
||||
private:
|
||||
|
||||
@ -225,6 +241,8 @@ class Genode::Register_set : Noncopyable
|
||||
typedef typename Genode::Register<_ACCESS_WIDTH>::access_t
|
||||
access_t;
|
||||
|
||||
static_assert(OFFSET + sizeof(access_t) <= REGISTER_SET_SIZE);
|
||||
|
||||
/**
|
||||
* A region within a register
|
||||
*
|
||||
@ -333,28 +351,27 @@ class Genode::Register_set : Noncopyable
|
||||
Compound_array;
|
||||
};
|
||||
|
||||
|
||||
struct Dst { off_t offset; uint8_t shift; };
|
||||
|
||||
/**
|
||||
* Calculate destination of an array-item access
|
||||
*
|
||||
* \param offset Gets overridden with the offset of the
|
||||
* access type instance, that contains the
|
||||
* access destination
|
||||
* \param shift Gets overridden with the shift of the
|
||||
* destination within the access type instance
|
||||
* targeted by 'offset'.
|
||||
* \param index index of the targeted array item
|
||||
*/
|
||||
static inline void dst(off_t & offset,
|
||||
unsigned long & shift,
|
||||
unsigned long const index)
|
||||
static constexpr Dst dst(unsigned long index)
|
||||
{
|
||||
unsigned long const bit_off = index << ITEM_WIDTH_LOG2;
|
||||
offset = (off_t) ((bit_off >> BYTE_WIDTH_LOG2)
|
||||
& ~(sizeof(access_t)-1) );
|
||||
shift = bit_off - ( offset << BYTE_WIDTH_LOG2 );
|
||||
off_t bit_offset = off_t(index << ITEM_WIDTH_LOG2);
|
||||
off_t byte_offset = bit_offset >> BYTE_WIDTH_LOG2;
|
||||
off_t offset = byte_offset & ~(sizeof(access_t) - 1);
|
||||
uint8_t shift = uint8_t(bit_offset - (offset << BYTE_WIDTH_LOG2));
|
||||
offset += OFFSET;
|
||||
|
||||
return { .offset = offset, .shift = shift };
|
||||
}
|
||||
|
||||
static_assert(dst(MAX_INDEX).offset + sizeof(access_t) <= REGISTER_SET_SIZE);
|
||||
|
||||
/**
|
||||
* Calc destination of a simple array-item access without shift
|
||||
*
|
||||
@ -485,10 +502,9 @@ class Genode::Register_set : Noncopyable
|
||||
|
||||
/* access width and item width differ */
|
||||
} else {
|
||||
long unsigned shift;
|
||||
Array::dst(offset, shift, index);
|
||||
return (Plain_access::read<access_t>(_plain_access, offset)
|
||||
>> shift) & Array::ITEM_MASK;
|
||||
typename Array::Dst dst { Array::dst(index) };
|
||||
return (Plain_access::read<access_t>(_plain_access, dst.offset)
|
||||
>> dst.shift) & Array::ITEM_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,8 +533,7 @@ class Genode::Register_set : Noncopyable
|
||||
|
||||
/* access width and item width differ */
|
||||
} else {
|
||||
long unsigned shift;
|
||||
Array::dst(offset, shift, index);
|
||||
typename Array::Dst dst { Array::dst(index) };
|
||||
|
||||
/* insert new value into old register value */
|
||||
access_t write_value;
|
||||
@ -530,12 +545,12 @@ class Genode::Register_set : Noncopyable
|
||||
|
||||
/* apply bitfield to the old register value */
|
||||
write_value = Plain_access::read<access_t>(_plain_access,
|
||||
offset);
|
||||
write_value &= ~(Array::ITEM_MASK << shift);
|
||||
dst.offset);
|
||||
write_value &= ~(Array::ITEM_MASK << dst.shift);
|
||||
}
|
||||
/* apply bitfield value and override register */
|
||||
write_value |= (value & Array::ITEM_MASK) << shift;
|
||||
Plain_access::write<access_t>(_plain_access, offset,
|
||||
write_value |= (value & Array::ITEM_MASK) << dst.shift;
|
||||
Plain_access::write<access_t>(_plain_access, dst.offset,
|
||||
write_value);
|
||||
}
|
||||
}
|
||||
@ -680,17 +695,6 @@ class Genode::Register_set : Noncopyable
|
||||
explicit Microseconds(uint64_t value) : value(value) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for delaying the execution of a calling thread
|
||||
*/
|
||||
struct Delayer : Interface
|
||||
{
|
||||
/**
|
||||
* Delay execution of the caller for 'us' microseconds
|
||||
*/
|
||||
virtual void usleep(uint64_t us) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wait until a list of IO conditions is met
|
||||
|
@ -58,9 +58,9 @@ struct Cpu_state : Register<16>
|
||||
/**
|
||||
* Exemplary MMIO region type
|
||||
*/
|
||||
struct Test_mmio : public Mmio
|
||||
struct Test_mmio : public Mmio<MMIO_SIZE>
|
||||
{
|
||||
Test_mmio(addr_t const base) : Mmio(base) { }
|
||||
Test_mmio(addr_t const base) : Mmio({(char *)base, Mmio::SIZE}) { }
|
||||
|
||||
struct Reg_64 : Register<0x00, 64>
|
||||
{
|
||||
@ -129,7 +129,7 @@ struct Test_mmio : public Mmio
|
||||
|
||||
struct Simple_array_1 : Register_array<0x0, 32, 2, 32> { };
|
||||
|
||||
struct Simple_array_2 : Register_array<0x2, 16, 4, 16> { };
|
||||
struct Simple_array_2 : Register_array<0x2, 16, 3, 16> { };
|
||||
|
||||
struct Strict_reg : Register<0x0, 32, true>
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ using namespace Genode;
|
||||
|
||||
Timer::Time_source::Time_source(Env &env)
|
||||
:
|
||||
Attached_mmio(env, EPIT_2_MMIO_BASE, EPIT_2_MMIO_SIZE),
|
||||
Attached_mmio(env, {(char *)EPIT_2_MMIO_BASE, EPIT_2_MMIO_SIZE}),
|
||||
Signalled_time_source(env),
|
||||
_timer_irq(env, unsigned(EPIT_2_IRQ))
|
||||
{
|
||||
|
@ -26,8 +26,7 @@
|
||||
|
||||
namespace Timer { class Time_source; }
|
||||
|
||||
|
||||
class Timer::Time_source : private Genode::Attached_mmio,
|
||||
class Timer::Time_source : private Genode::Attached_mmio<0x14>,
|
||||
public Genode::Signalled_time_source
|
||||
{
|
||||
private:
|
||||
|
@ -51,9 +51,9 @@ class Pci_driver
|
||||
|
||||
struct Device
|
||||
{
|
||||
Platform::Device dev;
|
||||
Platform::Device::Irq irq;
|
||||
Platform::Device::Mmio mmio;
|
||||
Platform::Device dev;
|
||||
Platform::Device::Irq irq;
|
||||
Platform::Device::Mmio<0> mmio;
|
||||
|
||||
Device(Platform::Connection &pci,
|
||||
Platform::Device::Name const &name)
|
||||
|
@ -148,7 +148,7 @@ extern "C" void dde_mdelay(unsigned long msecs)
|
||||
|
||||
struct Range { addr_t start; size_t size; };
|
||||
|
||||
using Io_mem = Platform::Device::Mmio;
|
||||
using Io_mem = Platform::Device::Mmio<0>;
|
||||
using Io_port = Platform::Device::Io_port_range;
|
||||
|
||||
struct Pci_driver
|
||||
|
@ -45,14 +45,14 @@ class Lx_kit::Device : List<Device>::Element
|
||||
|
||||
struct Io_mem : List<Io_mem>::Element
|
||||
{
|
||||
using Index = Platform::Device::Mmio::Index;
|
||||
using Index = Platform::Device::Mmio<0>::Index;
|
||||
|
||||
Index idx;
|
||||
addr_t addr;
|
||||
size_t size;
|
||||
unsigned pci_bar;
|
||||
|
||||
Constructible<Platform::Device::Mmio> io_mem {};
|
||||
Constructible<Platform::Device::Mmio<0> > io_mem {};
|
||||
|
||||
bool match(addr_t addr, size_t size);
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Genode { class Attached_mmio; }
|
||||
namespace Genode { template <size_t> class Attached_mmio; }
|
||||
|
||||
|
||||
/**
|
||||
@ -30,8 +30,9 @@ namespace Genode { class Attached_mmio; }
|
||||
* and cast the received address. This helper undertakes all of this
|
||||
* generic work when inheriting from it.
|
||||
*/
|
||||
template <Genode::size_t SIZE>
|
||||
class Genode::Attached_mmio : public Attached_io_mem_dataspace,
|
||||
public Mmio
|
||||
public Mmio<SIZE>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -49,10 +50,9 @@ class Genode::Attached_mmio : public Attached_io_mem_dataspace,
|
||||
* \throw Out_of_caps
|
||||
* \throw Region_map::Region_conflict
|
||||
*/
|
||||
Attached_mmio(Env &env, addr_t base, size_t size,
|
||||
bool write_combined = false)
|
||||
: Attached_io_mem_dataspace(env, base, size, write_combined),
|
||||
Mmio((addr_t)local_addr<void>()) { }
|
||||
Attached_mmio(Env &env, Byte_range_ptr const &range, bool write_combined = false)
|
||||
: Attached_io_mem_dataspace(env, (addr_t)range.start, range.num_bytes, write_combined),
|
||||
Mmio<SIZE>({local_addr<char>(), range.num_bytes}) { }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_MMIO_H_ */
|
||||
|
@ -33,7 +33,7 @@ namespace Pci {
|
||||
};
|
||||
};
|
||||
|
||||
struct Pci::Config : Genode::Mmio
|
||||
struct Pci::Config : Genode::Mmio<0x45>
|
||||
{
|
||||
struct Vendor : Register<0x0, 16>
|
||||
{
|
||||
@ -82,7 +82,7 @@ struct Pci::Config : Genode::Mmio
|
||||
struct Multi_function : Bitfield<7,1> {};
|
||||
};
|
||||
|
||||
struct Base_address : Mmio
|
||||
struct Base_address : Mmio<0x8>
|
||||
{
|
||||
struct Bar_32bit : Register<0, 32>
|
||||
{
|
||||
@ -126,7 +126,7 @@ struct Pci::Config : Genode::Mmio
|
||||
return _conf_value;
|
||||
}
|
||||
|
||||
Base_address(Genode::addr_t base) : Mmio(base) { }
|
||||
Base_address(Genode::Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
bool valid() { return _conf() != 0; }
|
||||
|
||||
@ -202,7 +202,8 @@ struct Pci::Config : Genode::Mmio
|
||||
** PCI Capabilities **
|
||||
**********************/
|
||||
|
||||
struct Pci_capability : Genode::Mmio
|
||||
template <Genode::size_t SIZE>
|
||||
struct Pci_capability : Genode::Mmio<SIZE>
|
||||
{
|
||||
struct Id : Register<0,8>
|
||||
{
|
||||
@ -223,11 +224,17 @@ struct Pci::Config : Genode::Mmio
|
||||
|
||||
struct Pointer : Register<1,8> {};
|
||||
|
||||
using Genode::Mmio::Mmio;
|
||||
using Mmio<SIZE>::Mmio;
|
||||
};
|
||||
|
||||
|
||||
struct Power_management_capability : Pci_capability
|
||||
struct Pci_capability_header : Pci_capability<0x2>
|
||||
{
|
||||
using Pci_capability::Pci_capability;
|
||||
};
|
||||
|
||||
|
||||
struct Power_management_capability : Pci_capability<0x8>
|
||||
{
|
||||
struct Capabilities : Register<0x2, 16> {};
|
||||
|
||||
@ -279,7 +286,7 @@ struct Pci::Config : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Msi_capability : Pci_capability
|
||||
struct Msi_capability : Pci_capability<0xe>
|
||||
{
|
||||
struct Control : Register<0x2, 16>
|
||||
{
|
||||
@ -315,7 +322,7 @@ struct Pci::Config : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Msi_x_capability : Pci_capability
|
||||
struct Msi_x_capability : Pci_capability<0xc>
|
||||
{
|
||||
struct Control : Register<0x2, 16>
|
||||
{
|
||||
@ -337,7 +344,7 @@ struct Pci::Config : Genode::Mmio
|
||||
struct Offset : Bitfield<3, 29> {};
|
||||
};
|
||||
|
||||
struct Table_entry : Genode::Mmio
|
||||
struct Table_entry : Genode::Mmio<0x10>
|
||||
{
|
||||
enum { SIZE = 16 };
|
||||
|
||||
@ -349,7 +356,7 @@ struct Pci::Config : Genode::Mmio
|
||||
struct Mask : Bitfield <0, 1> { };
|
||||
};
|
||||
|
||||
using Genode::Mmio::Mmio;
|
||||
using Mmio::Mmio;
|
||||
};
|
||||
|
||||
using Pci_capability::Pci_capability;
|
||||
@ -372,7 +379,7 @@ struct Pci::Config : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Pci_express_capability : Pci_capability
|
||||
struct Pci_express_capability : Pci_capability<0x3c>
|
||||
{
|
||||
struct Capabilities : Register<0x2, 16> {};
|
||||
|
||||
@ -484,7 +491,8 @@ struct Pci::Config : Genode::Mmio
|
||||
|
||||
enum { PCI_E_EXTENDED_CAPS_OFFSET = 0x100U };
|
||||
|
||||
struct Pci_express_extended_capability : Genode::Mmio
|
||||
template<Genode::size_t SIZE>
|
||||
struct Pci_express_extended_capability : Genode::Mmio<SIZE>
|
||||
{
|
||||
struct Id : Register<0x0, 16>
|
||||
{
|
||||
@ -504,11 +512,17 @@ struct Pci::Config : Genode::Mmio
|
||||
struct Offset : Bitfield<4, 12> {};
|
||||
};
|
||||
|
||||
using Genode::Mmio::Mmio;
|
||||
using Mmio<SIZE>::Mmio;
|
||||
};
|
||||
|
||||
|
||||
struct Advanced_error_reporting_capability : Pci_express_extended_capability
|
||||
struct Pci_express_extended_capability_header : Pci_express_extended_capability<0x4>
|
||||
{
|
||||
using Pci_express_extended_capability::Pci_express_extended_capability;
|
||||
};
|
||||
|
||||
|
||||
struct Advanced_error_reporting_capability : Pci_express_extended_capability<0x34>
|
||||
{
|
||||
struct Uncorrectable_error_status : Register<0x4, 32> {};
|
||||
struct Correctable_error_status : Register<0x10, 32> {};
|
||||
@ -547,8 +561,8 @@ struct Pci::Config : Genode::Mmio
|
||||
Genode::Constructible<Pci_express_capability> pci_e_cap {};
|
||||
Genode::Constructible<Advanced_error_reporting_capability> adv_err_cap {};
|
||||
|
||||
Base_address bar0 { base() + BASE_ADDRESS_0 };
|
||||
Base_address bar1 { base() + BASE_ADDRESS_0 + 0x4 };
|
||||
Base_address bar0 { Mmio::range_at(BASE_ADDRESS_0) };
|
||||
Base_address bar1 { Mmio::range_at(BASE_ADDRESS_0 + 0x4) };
|
||||
|
||||
void clear_errors() {
|
||||
if (adv_err_cap.constructed()) adv_err_cap->clear(); }
|
||||
@ -562,21 +576,22 @@ struct Pci::Config : Genode::Mmio
|
||||
|
||||
uint16_t off = read<Capability_pointer>();
|
||||
while (off) {
|
||||
Pci_capability cap(base() + off);
|
||||
switch(cap.read<Pci_capability::Id>()) {
|
||||
case Pci_capability::Id::POWER_MANAGEMENT:
|
||||
power_cap.construct(base()+off); break;
|
||||
case Pci_capability::Id::MSI:
|
||||
msi_cap.construct(base()+off); break;
|
||||
case Pci_capability::Id::MSI_X:
|
||||
msi_x_cap.construct(base()+off); break;
|
||||
case Pci_capability::Id::PCI_E:
|
||||
pci_e_cap.construct(base()+off); break;
|
||||
using Capability_header = Pci_capability_header;
|
||||
Capability_header cap(Mmio::range_at(off));
|
||||
switch(cap.read<Capability_header::Id>()) {
|
||||
case Capability_header::Id::POWER_MANAGEMENT:
|
||||
power_cap.construct(Mmio::range_at(off)); break;
|
||||
case Capability_header::Id::MSI:
|
||||
msi_cap.construct(Mmio::range_at(off)); break;
|
||||
case Capability_header::Id::MSI_X:
|
||||
msi_x_cap.construct(Mmio::range_at(off)); break;
|
||||
case Capability_header::Id::PCI_E:
|
||||
pci_e_cap.construct(Mmio::range_at(off)); break;
|
||||
|
||||
default:
|
||||
/* ignore unhandled capability */ ;
|
||||
}
|
||||
off = cap.read<Pci_capability::Pointer>();
|
||||
off = cap.read<Capability_header::Pointer>();
|
||||
}
|
||||
|
||||
if (!pci_e_cap.constructed())
|
||||
@ -584,21 +599,22 @@ struct Pci::Config : Genode::Mmio
|
||||
|
||||
off = PCI_E_EXTENDED_CAPS_OFFSET;
|
||||
while (off) {
|
||||
Pci_express_extended_capability cap(base() + off);
|
||||
switch (cap.read<Pci_express_extended_capability::Id>()) {
|
||||
case Pci_express_extended_capability::Id::INVALID:
|
||||
using Capability_header = Pci_express_extended_capability_header;
|
||||
Capability_header cap(Mmio::range_at(off));
|
||||
switch (cap.read<Capability_header::Id>()) {
|
||||
case Capability_header::Id::INVALID:
|
||||
return;
|
||||
case Pci_express_extended_capability::Id::ADVANCED_ERROR_REPORTING:
|
||||
adv_err_cap.construct(base() + off); break;
|
||||
case Capability_header::Id::ADVANCED_ERROR_REPORTING:
|
||||
adv_err_cap.construct(Mmio::range_at(off)); break;
|
||||
|
||||
default:
|
||||
/* ignore unhandled extended capability */ ;
|
||||
}
|
||||
off = cap.read<Pci_express_extended_capability::Next_and_version::Offset>();
|
||||
off = cap.read<Capability_header::Next_and_version::Offset>();
|
||||
}
|
||||
}
|
||||
|
||||
using Genode::Mmio::Mmio;
|
||||
using Mmio::Mmio;
|
||||
|
||||
bool valid() {
|
||||
return read<Vendor>() != Vendor::INVALID; }
|
||||
@ -612,13 +628,12 @@ struct Pci::Config : Genode::Mmio
|
||||
template <typename MEM_FN, typename IO_FN>
|
||||
void for_each_bar(MEM_FN const & memory, IO_FN const & io)
|
||||
{
|
||||
Genode::addr_t const reg_addr = base() + BASE_ADDRESS_0;
|
||||
Genode::size_t const reg_cnt =
|
||||
(read<Header_type::Type>()) ? BASE_ADDRESS_COUNT_TYPE_1
|
||||
: BASE_ADDRESS_COUNT_TYPE_0;
|
||||
|
||||
for (unsigned i = 0; i < reg_cnt; i++) {
|
||||
Base_address reg0(reg_addr + i*0x4);
|
||||
Base_address reg0 { Mmio::range_at(BASE_ADDRESS_0 + i*0x4) };
|
||||
if (!reg0.valid())
|
||||
continue;
|
||||
if (reg0.memory()) {
|
||||
@ -634,7 +649,7 @@ struct Pci::Config : Genode::Mmio
|
||||
if (idx > 5 || (idx > 1 && bridge()))
|
||||
return;
|
||||
|
||||
Base_address bar { base() + BASE_ADDRESS_0 + idx*0x4 };
|
||||
Base_address bar { Mmio::range_at(BASE_ADDRESS_0 + idx*0x4) };
|
||||
bar.set(addr);
|
||||
}
|
||||
|
||||
@ -660,10 +675,10 @@ struct Pci::Config_type0 : Pci::Config
|
||||
|
||||
using Pci::Config::Config;
|
||||
|
||||
Base_address bar2 { base() + BASE_ADDRESS_0 + 0x8 };
|
||||
Base_address bar3 { base() + BASE_ADDRESS_0 + 0xc };
|
||||
Base_address bar4 { base() + BASE_ADDRESS_0 + 0x10 };
|
||||
Base_address bar5 { base() + BASE_ADDRESS_0 + 0x14 };
|
||||
Base_address bar2 { Mmio::range_at(BASE_ADDRESS_0 + 0x8 ) };
|
||||
Base_address bar3 { Mmio::range_at(BASE_ADDRESS_0 + 0xc ) };
|
||||
Base_address bar4 { Mmio::range_at(BASE_ADDRESS_0 + 0x10) };
|
||||
Base_address bar5 { Mmio::range_at(BASE_ADDRESS_0 + 0x14) };
|
||||
|
||||
struct Subsystem_vendor : Register<0x2c, 16> { };
|
||||
struct Subsystem_device : Register<0x2e, 16> { };
|
||||
|
@ -28,7 +28,7 @@ class Platform::Device : Interface, Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
struct Mmio;
|
||||
template <size_t> struct Mmio;
|
||||
struct Irq;
|
||||
struct Io_port_range;
|
||||
|
||||
@ -38,8 +38,6 @@ class Platform::Device : Interface, Noncopyable
|
||||
|
||||
typedef Device_interface::Range Range;
|
||||
|
||||
friend class Mmio;
|
||||
|
||||
::Platform::Connection &_platform;
|
||||
|
||||
Capability<Device_interface> _cap;
|
||||
@ -86,7 +84,8 @@ class Platform::Device : Interface, Noncopyable
|
||||
};
|
||||
|
||||
|
||||
class Platform::Device::Mmio : Range, Attached_dataspace, public Genode::Mmio
|
||||
template <Genode::size_t SIZE>
|
||||
class Platform::Device::Mmio : Range, Attached_dataspace, public Genode::Mmio<SIZE>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -108,7 +107,7 @@ class Platform::Device::Mmio : Range, Attached_dataspace, public Genode::Mmio
|
||||
Mmio(Device &device, Index index)
|
||||
:
|
||||
Attached_dataspace(device._rm(), _ds_cap(device, index.value)),
|
||||
Genode::Mmio(_local_addr())
|
||||
Genode::Mmio<SIZE>({(char *)_local_addr(), size()})
|
||||
{ }
|
||||
|
||||
explicit Mmio(Device &device) : Mmio(device, Index { 0 }) { }
|
||||
|
@ -25,7 +25,7 @@ namespace Virtio {
|
||||
}
|
||||
|
||||
|
||||
class Virtio::Device : Platform::Device::Mmio
|
||||
class Virtio::Device : Platform::Device::Mmio<0x200>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -102,7 +102,7 @@ class Virtio::Device : Platform::Device::Mmio
|
||||
|
||||
Device(Platform::Device & device)
|
||||
:
|
||||
Platform::Device::Mmio(device), _irq(device, {0})
|
||||
Platform::Device::Mmio<SIZE>(device), _irq(device, {0})
|
||||
{
|
||||
if (read<Magic>() != VIRTIO_MMIO_MAGIC) {
|
||||
throw Invalid_device(); }
|
||||
|
@ -23,7 +23,7 @@ namespace Virtio {
|
||||
class Device;
|
||||
}
|
||||
|
||||
struct Virtio::Device_mmio : public Genode::Mmio
|
||||
struct Virtio::Device_mmio : public Genode::Mmio<0x100>
|
||||
{
|
||||
struct DeviceFeatureSelect : Register<0x00, 32> { };
|
||||
struct DeviceFeature : Register<0x04, 32> { };
|
||||
@ -96,13 +96,13 @@ class Virtio::Device
|
||||
Platform::Device _device { _plat };
|
||||
Platform::Device::Irq _irq { _device, { 0 } };
|
||||
|
||||
Constructible<Platform::Device::Mmio> _mmio[MMIO_MAX] { };
|
||||
Constructible<Platform::Device::Mmio<0> > _mmio[MMIO_MAX] { };
|
||||
|
||||
Mmio _cfg_common { _bar_offset("common") };
|
||||
Mmio _dev_config { _bar_offset("device") };
|
||||
Mmio _notify { _bar_offset("notify") };
|
||||
Mmio _isr { _bar_offset("irq_status") };
|
||||
size_t _notify_offset_multiplier { 0 };
|
||||
Device_mmio _cfg_common { _bar_range("common") };
|
||||
Device_mmio _dev_config { _bar_range("device") };
|
||||
Device_mmio _notify { _bar_range("notify") };
|
||||
Device_mmio _isr { _bar_range("irq_status") };
|
||||
size_t _notify_offset_multiplier { 0 };
|
||||
|
||||
template <typename FN>
|
||||
void with_virtio_range(String<16> type, FN const & fn)
|
||||
@ -123,7 +123,7 @@ class Virtio::Device
|
||||
});
|
||||
}
|
||||
|
||||
addr_t _bar_offset(String<16> type)
|
||||
Byte_range_ptr _bar_range(String<16> type)
|
||||
{
|
||||
unsigned idx = MMIO_MAX;
|
||||
addr_t off = ~0UL;
|
||||
@ -137,8 +137,8 @@ class Virtio::Device
|
||||
|
||||
if (!_mmio[idx].constructed())
|
||||
_mmio[idx].construct(_device,
|
||||
Platform::Device::Mmio::Index{idx});
|
||||
return _mmio[idx]->base() + off;
|
||||
Platform::Device::Mmio<0>::Index{idx});
|
||||
return _mmio[idx]->range_at(off);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -56,7 +56,7 @@ struct Main
|
||||
bus_t parse_pci_function(Bdf bdf, Config & cfg,
|
||||
addr_t cfg_phys_base,
|
||||
Xml_generator & generator, unsigned & msi);
|
||||
bus_t parse_pci_bus(bus_t bus, addr_t base, addr_t phys_base,
|
||||
bus_t parse_pci_bus(bus_t bus, Byte_range_ptr const & range, addr_t phys_base,
|
||||
Xml_generator & generator, unsigned & msi);
|
||||
|
||||
void parse_irq_override_rules(Xml_node & xml);
|
||||
@ -94,7 +94,7 @@ bus_t Main::parse_pci_function(Bdf bdf,
|
||||
/* check for bridges */
|
||||
if (cfg.read<Config::Header_type::Type>()) {
|
||||
for_bridge(bdf.bus, [&] (Bridge & parent) {
|
||||
Config_type1 bcfg(cfg.base());
|
||||
Config_type1 bcfg(cfg.range());
|
||||
new (heap) Bridge(parent.sub_bridges, bdf,
|
||||
bcfg.secondary_bus_number(),
|
||||
bcfg.subordinate_bus_number());
|
||||
@ -142,7 +142,7 @@ bus_t Main::parse_pci_function(Bdf bdf,
|
||||
gen.attribute("revision", string(cfg.read<Cc::Revision>()));
|
||||
gen.attribute("bridge", cfg.bridge() ? "yes" : "no");
|
||||
if (!cfg.bridge()) {
|
||||
C0 cfg0(cfg.base());
|
||||
C0 cfg0(cfg.range());
|
||||
gen.attribute("sub_vendor_id",
|
||||
string(cfg0.read<C0::Subsystem_vendor>()));
|
||||
gen.attribute("sub_device_id",
|
||||
@ -286,17 +286,17 @@ bus_t Main::parse_pci_function(Bdf bdf,
|
||||
}
|
||||
|
||||
|
||||
bus_t Main::parse_pci_bus(bus_t bus,
|
||||
addr_t base,
|
||||
addr_t phys_base,
|
||||
Xml_generator & generator,
|
||||
unsigned & msi_number)
|
||||
bus_t Main::parse_pci_bus(bus_t bus,
|
||||
Byte_range_ptr const & range,
|
||||
addr_t phys_base,
|
||||
Xml_generator & generator,
|
||||
unsigned & msi_number)
|
||||
{
|
||||
bus_t max_subordinate_bus = bus;
|
||||
|
||||
auto per_function = [&] (addr_t config_base, addr_t config_phys_base,
|
||||
auto per_function = [&] (Byte_range_ptr const & config_range, addr_t config_phys_base,
|
||||
dev_t dev, func_t fn) {
|
||||
Config cfg(config_base);
|
||||
Config cfg(config_range);
|
||||
if (!cfg.valid())
|
||||
return true;
|
||||
|
||||
@ -312,10 +312,10 @@ bus_t Main::parse_pci_bus(bus_t bus,
|
||||
for (dev_t dev = 0; dev < DEVICES_PER_BUS_MAX; dev++) {
|
||||
for (func_t fn = 0; fn < FUNCTION_PER_DEVICE_MAX; fn++) {
|
||||
unsigned factor = dev * FUNCTION_PER_DEVICE_MAX + fn;
|
||||
addr_t config_base = base + factor * FUNCTION_CONFIG_SPACE_SIZE;
|
||||
addr_t config_phys_base =
|
||||
phys_base + factor * FUNCTION_CONFIG_SPACE_SIZE;
|
||||
if (!per_function(config_base, config_phys_base, dev, fn))
|
||||
off_t config_offset = factor * FUNCTION_CONFIG_SPACE_SIZE;
|
||||
Byte_range_ptr config_range { range.start + config_offset, range.num_bytes - config_offset };
|
||||
addr_t config_phys_base = phys_base + config_offset;
|
||||
if (!per_function(config_range, config_phys_base, dev, fn))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -504,7 +504,7 @@ void Main::parse_pci_config_spaces(Xml_node & xml, Xml_generator & generator)
|
||||
pci_config_ds.construct(env, offset, BUS_SIZE);
|
||||
bus_t const subordinate_bus =
|
||||
parse_pci_bus((bus_t)bus + bus_off,
|
||||
(addr_t)pci_config_ds->local_addr<void>(),
|
||||
{pci_config_ds->local_addr<char>(), BUS_SIZE},
|
||||
offset, generator, msi_number);
|
||||
|
||||
max_subordinate_bus = max(max_subordinate_bus, subordinate_bus);
|
||||
|
@ -115,13 +115,13 @@ struct Generic
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
struct Dmar_common : Genode::Mmio
|
||||
struct Dmar_common : Genode::Mmio<0x4>
|
||||
{
|
||||
struct Type : Register<0x0, 16> {
|
||||
enum { DRHD= 0U, RMRR = 0x1U, ATSR = 0x2U, RHSA = 0x3U }; };
|
||||
struct Length : Register<0x2, 16> { };
|
||||
|
||||
Dmar_common(addr_t mmio) : Genode::Mmio(mmio) { }
|
||||
Dmar_common(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
|
||||
@ -143,7 +143,7 @@ struct Dmar_struct_header : Generic
|
||||
{
|
||||
addr_t addr = dmar_entry_start();
|
||||
while (addr < dmar_entry_end()) {
|
||||
Dmar_common dmar(addr);
|
||||
Dmar_common dmar({(char *)addr, dmar_entry_end() - addr});
|
||||
|
||||
func(dmar);
|
||||
|
||||
@ -163,38 +163,43 @@ struct Dmar_struct_header : Generic
|
||||
|
||||
|
||||
/* Intel VT-d IO Spec - 8.3.1. */
|
||||
struct Device_scope : Genode::Mmio
|
||||
struct Device_scope : Genode::Mmio<0x6>
|
||||
{
|
||||
enum { MAX_PATHS = 4 };
|
||||
|
||||
Device_scope(addr_t a) : Genode::Mmio(a) { }
|
||||
Device_scope(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
struct Type : Register<0x0, 8> { enum { PCI_END_POINT = 0x1 }; };
|
||||
struct Length : Register<0x1, 8> { };
|
||||
struct Bus : Register<0x5, 8> { };
|
||||
|
||||
struct Path : Register_array<0x6, 8, MAX_PATHS, 16> {
|
||||
struct Dev : Bitfield<0,8> { };
|
||||
struct Func : Bitfield<8,8> { };
|
||||
struct Path : Genode::Mmio<0x2>
|
||||
{
|
||||
Path(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
struct Dev : Register<0, 8> { };
|
||||
struct Func : Register<1, 8> { };
|
||||
|
||||
uint8_t dev() const { return read<Dev >(); }
|
||||
uint8_t func() const { return read<Func>(); }
|
||||
};
|
||||
|
||||
unsigned count() const {
|
||||
unsigned const length = read<Length>();
|
||||
if (length < 6)
|
||||
return 0;
|
||||
void for_each_path(auto const &fn) const
|
||||
{
|
||||
auto const length = read<Length>();
|
||||
|
||||
unsigned paths = (read<Length>() - 6) / 2;
|
||||
if (paths > MAX_PATHS) {
|
||||
Genode::error("Device_scope: more paths (", paths, ") than"
|
||||
" supported (", (int)MAX_PATHS,")");
|
||||
return MAX_PATHS;
|
||||
unsigned offset = Device_scope::SIZE;
|
||||
|
||||
while (offset < length) {
|
||||
Path const path(Mmio::range_at(offset));
|
||||
|
||||
fn(path);
|
||||
|
||||
offset += Path::SIZE;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
};
|
||||
|
||||
/* DMA Remapping Hardware Definition - Intel VT-d IO Spec - 8.3. */
|
||||
struct Dmar_drhd : Genode::Mmio
|
||||
struct Dmar_drhd : Genode::Mmio<0x10>
|
||||
{
|
||||
struct Length : Register<0x2, 16> { };
|
||||
struct Flags : Register<0x4, 8> { };
|
||||
@ -203,52 +208,52 @@ struct Dmar_drhd : Genode::Mmio
|
||||
struct Segment : Register<0x6, 16> { };
|
||||
struct Phys : Register<0x8, 64> { };
|
||||
|
||||
Dmar_drhd(addr_t a) : Genode::Mmio(a) { }
|
||||
Dmar_drhd(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
template <typename FUNC>
|
||||
void apply(FUNC const &func = [] () { } )
|
||||
{
|
||||
addr_t addr = base() + 16;
|
||||
while (addr < base() + read<Length>()) {
|
||||
Device_scope scope(addr);
|
||||
off_t offset = 16;
|
||||
while (offset < read<Length>()) {
|
||||
Device_scope scope(Mmio::range_at(offset));
|
||||
|
||||
func(scope);
|
||||
|
||||
addr = scope.base() + scope.read<Device_scope::Length>();
|
||||
offset += scope.read<Device_scope::Length>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* DMA Remapping Reporting structure - Intel VT-d IO Spec - 8.3. */
|
||||
struct Dmar_rmrr : Genode::Mmio
|
||||
struct Dmar_rmrr : Genode::Mmio<0x18>
|
||||
{
|
||||
struct Length : Register<0x02, 16> { };
|
||||
struct Base : Register<0x08, 64> { };
|
||||
struct Limit : Register<0x10, 64> { };
|
||||
|
||||
Dmar_rmrr(addr_t a) : Genode::Mmio(a) { }
|
||||
Dmar_rmrr(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
template <typename FUNC>
|
||||
void apply(FUNC const &func = [] () { } )
|
||||
{
|
||||
addr_t addr = base() + 24;
|
||||
while (addr < base() + read<Length>()) {
|
||||
Device_scope scope(addr);
|
||||
addr_t offset = 24;
|
||||
while (offset < read<Length>()) {
|
||||
Device_scope scope(Mmio::range_at(offset));
|
||||
|
||||
func(scope);
|
||||
|
||||
addr = scope.base() + scope.read<Device_scope::Length>();
|
||||
offset += scope.read<Device_scope::Length>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* I/O Virtualization Definition Blocks for AMD IO-MMU */
|
||||
struct Ivdb : Genode::Mmio
|
||||
struct Ivdb : Genode::Mmio<0x4>
|
||||
{
|
||||
struct Type : Register<0x00, 8> { };
|
||||
struct Length : Register<0x02, 16> { };
|
||||
|
||||
Ivdb(addr_t const addr) : Genode::Mmio(addr) { }
|
||||
Ivdb(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
|
||||
@ -275,7 +280,7 @@ struct Ivdb_entry : public List<Ivdb_entry>::Element
|
||||
|
||||
|
||||
/* I/O Virtualization Reporting Structure (IVRS) for AMD IO-MMU */
|
||||
struct Ivrs : Genode::Mmio
|
||||
struct Ivrs : Genode::Mmio<0x28>
|
||||
{
|
||||
struct Length : Register<0x04, 32> { };
|
||||
struct Ivinfo : Register<0x24, 32> {
|
||||
@ -284,37 +289,33 @@ struct Ivrs : Genode::Mmio
|
||||
|
||||
static constexpr unsigned min_size() { return 0x30; }
|
||||
|
||||
Ivrs(addr_t const table) : Genode::Mmio(table) { }
|
||||
Ivrs(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
void parse(Allocator &alloc)
|
||||
{
|
||||
addr_t addr = base() + 0x30;
|
||||
while (addr < base() + read<Ivrs::Length>()) {
|
||||
uint32_t offset = 0x30;
|
||||
while (offset < read<Ivrs::Length>()) {
|
||||
bool dmar = Ivinfo::Dmar::get(read<Ivinfo::Dmar>());
|
||||
if (dmar)
|
||||
Genode::warning("Predefined regions should be added to IOMMU");
|
||||
|
||||
Ivdb ivdb(addr);
|
||||
Ivdb ivdb(Mmio::range_at(offset));
|
||||
|
||||
uint32_t const type = ivdb.read<Ivdb::Type>();
|
||||
uint32_t const size = ivdb.read<Ivdb::Length>();
|
||||
|
||||
Ivdb_entry::list()->insert(new (&alloc) Ivdb_entry(type));
|
||||
|
||||
addr += size;
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Fixed ACPI description table (FADT) */
|
||||
struct Fadt : Genode::Mmio
|
||||
|
||||
struct Fadt_reset : Genode::Mmio<0x88>
|
||||
{
|
||||
size_t const size;
|
||||
Fadt_reset(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
Fadt(addr_t mmio, size_t size) : Genode::Mmio(mmio), size(size) { }
|
||||
|
||||
struct Dsdt : Register<0x28, 32> { };
|
||||
struct Sci_int : Register<0x2e, 16> { };
|
||||
struct Features : Register<0x70, 32> {
|
||||
/* Table 5-35 Fixed ACPI Description Table Fixed Feature Flags */
|
||||
struct Reset : Bitfield<10, 1> { };
|
||||
@ -328,25 +329,31 @@ struct Fadt : Genode::Mmio
|
||||
struct Reset_reg : Register<0x78, 64> { };
|
||||
struct Reset_value : Register<0x80, 8> { };
|
||||
|
||||
bool dsdt_valid() {
|
||||
return size >= Dsdt::OFFSET + Dsdt::ACCESS_WIDTH / 8; }
|
||||
uint16_t io_port_reset() const { return read<Reset_reg>() & 0xffffu; }
|
||||
uint8_t reset_value() const { return read<Fadt_reset::Reset_value>(); }
|
||||
};
|
||||
|
||||
bool sci_int_valid() {
|
||||
return size >= Sci_int::OFFSET + Sci_int::ACCESS_WIDTH / 8; }
|
||||
|
||||
bool io_reset_supported()
|
||||
/* Fixed ACPI description table (FADT) */
|
||||
struct Fadt : Genode::Mmio<0x30>
|
||||
{
|
||||
Fadt(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
struct Dsdt : Register<0x28, 32> { };
|
||||
struct Sci_int : Register<0x2e, 16> { };
|
||||
|
||||
void detect_io_reset(auto const &range, auto const &fn) const
|
||||
{
|
||||
if (size < Reset_value::OFFSET + Reset_value::ACCESS_WIDTH / 8)
|
||||
return false;
|
||||
if (range.num_bytes < Fadt_reset::SIZE)
|
||||
return;
|
||||
|
||||
if (!read<Features::Reset>())
|
||||
return false;
|
||||
Fadt_reset const reset(range);
|
||||
|
||||
if (read<Reset_type::Address_space>() == Reset_type::Address_space::SYSTEM_IO)
|
||||
return true;
|
||||
if (!read<Fadt_reset::Features::Reset>())
|
||||
return;
|
||||
|
||||
warning("unsupported reset mode ", read<Reset_type::Address_space>());
|
||||
return false;
|
||||
if (read<Fadt_reset::Reset_type::Address_space>() == Fadt_reset::Reset_type::Address_space::SYSTEM_IO)
|
||||
fn(reset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -421,16 +428,16 @@ class Pci_config_space : public List<Pci_config_space>::Element
|
||||
return &_list;
|
||||
}
|
||||
|
||||
struct Config_space : Mmio
|
||||
struct Config_space : Mmio<0x100>
|
||||
{
|
||||
struct Vendor : Register<0x00, 16> { enum { INTEL = 0x8086 }; };
|
||||
struct Class : Register<0x0b, 8> { enum { DISPLAY = 0x3 }; };
|
||||
struct Asls : Register<0xfc, 32> { };
|
||||
|
||||
Config_space(addr_t mmio) : Mmio(mmio) { }
|
||||
Config_space(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
struct Opregion : Mmio
|
||||
struct Opregion : Mmio<0x3c6>
|
||||
{
|
||||
struct Minor : Register<0x16, 8> { };
|
||||
struct Major : Register<0x17, 8> { };
|
||||
@ -441,7 +448,7 @@ class Pci_config_space : public List<Pci_config_space>::Element
|
||||
struct Asle_rvda : Register<0x3ba, 64> { };
|
||||
struct Asle_rvds : Register<0x3c2, 32> { };
|
||||
|
||||
Opregion(addr_t mmio) : Mmio(mmio) { }
|
||||
Opregion(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
static void intel_opregion(Env &env)
|
||||
@ -459,7 +466,7 @@ class Pci_config_space : public List<Pci_config_space>::Element
|
||||
Attached_io_mem_dataspace pci_config(env, e->_base +
|
||||
config_offset * config_size,
|
||||
config_size);
|
||||
Config_space device((addr_t)pci_config.local_addr<void>());
|
||||
Config_space device({pci_config.local_addr<char>(), config_size});
|
||||
|
||||
if ((device.read<Config_space::Vendor>() != Config_space::Vendor::INTEL) ||
|
||||
(device.read<Config_space::Class>() != Config_space::Class::DISPLAY))
|
||||
@ -477,7 +484,7 @@ class Pci_config_space : public List<Pci_config_space>::Element
|
||||
|
||||
{
|
||||
Attached_io_mem_dataspace map_asls(env, phys_asls, asls_size);
|
||||
Opregion opregion((addr_t)map_asls.local_addr<void>());
|
||||
Opregion opregion({map_asls.local_addr<char>(), asls_size});
|
||||
|
||||
auto const rvda = opregion.read<Opregion::Asle_rvda>();
|
||||
auto const rvds = opregion.read<Opregion::Asle_rvds>();
|
||||
@ -1426,27 +1433,25 @@ class Acpi_table
|
||||
if (table.is_ivrs() && Ivrs::min_size() <= table->size) {
|
||||
log("Found IVRS");
|
||||
|
||||
Ivrs ivrs(reinterpret_cast<Genode::addr_t>(table->signature));
|
||||
Ivrs ivrs({(char *)table->signature, table->size});
|
||||
ivrs.parse(_heap);
|
||||
}
|
||||
|
||||
if (table.is_facp()) {
|
||||
Fadt fadt(reinterpret_cast<Genode::addr_t>(table->signature), table->size);
|
||||
if (table.is_facp() && (Fadt::SIZE <= table->size)) {
|
||||
Byte_range_ptr const range((char *)table->signature,
|
||||
table->size);
|
||||
|
||||
if (fadt.dsdt_valid())
|
||||
dsdt = fadt.read<Fadt::Dsdt>();
|
||||
Fadt fadt(range);
|
||||
|
||||
if (fadt.io_reset_supported()) {
|
||||
uint16_t const reset_io_port = fadt.read<Fadt::Reset_reg>() & 0xffffu;
|
||||
uint8_t const reset_value = fadt.read<Fadt::Reset_value>();
|
||||
dsdt = fadt.read<Fadt::Dsdt>();
|
||||
|
||||
_reset_info.construct(Reset_info { .io_port = reset_io_port,
|
||||
.value = reset_value });
|
||||
}
|
||||
if (fadt.sci_int_valid()) {
|
||||
_sci_int = fadt.read<Fadt::Sci_int>();
|
||||
_sci_int_valid = true;
|
||||
}
|
||||
_sci_int = fadt.read<Fadt::Sci_int>();
|
||||
_sci_int_valid = true;
|
||||
|
||||
fadt.detect_io_reset(range, [&](auto const &reset) {
|
||||
_reset_info.construct(Reset_info { .io_port = reset.io_port_reset(),
|
||||
.value = reset.reset_value() });
|
||||
});
|
||||
}
|
||||
|
||||
if (table.is_searched()) {
|
||||
@ -1651,20 +1656,16 @@ void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc,
|
||||
/* lambda definition for scope evaluation in rmrr */
|
||||
auto func_scope = [&] (Device_scope const &scope)
|
||||
{
|
||||
if (!scope.count())
|
||||
return;
|
||||
|
||||
xml.node("scope", [&] () {
|
||||
xml.attribute("bus_start", scope.read<Device_scope::Bus>());
|
||||
xml.attribute("type", scope.read<Device_scope::Type>());
|
||||
for (unsigned j = 0 ; j < scope.count(); j++) {
|
||||
|
||||
scope.for_each_path([&](auto const &path) {
|
||||
xml.node("path", [&] () {
|
||||
attribute_hex(xml, "dev",
|
||||
scope.read<Device_scope::Path::Dev>(j));
|
||||
attribute_hex(xml, "func",
|
||||
scope.read<Device_scope::Path::Func>(j));
|
||||
attribute_hex(xml, "dev" , path.dev());
|
||||
attribute_hex(xml, "func", path.func());
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -1676,7 +1677,7 @@ void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc,
|
||||
if (!ignore_drhd &&
|
||||
dmar.read<Dmar_common::Type>() == Dmar_common::Type::DRHD)
|
||||
{
|
||||
Dmar_drhd drhd(dmar.base());
|
||||
Dmar_drhd drhd(dmar.range());
|
||||
|
||||
size_t size_log2 = drhd.read<Dmar_drhd::Size::Num_pages>() + 12;
|
||||
|
||||
@ -1692,7 +1693,7 @@ void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc,
|
||||
if (dmar.read<Dmar_common::Type>() != Dmar_common::Type::RMRR)
|
||||
return;
|
||||
|
||||
Dmar_rmrr rmrr(dmar.base());
|
||||
Dmar_rmrr rmrr(dmar.range());
|
||||
|
||||
xml.node("rmrr", [&] () {
|
||||
attribute_hex(xml, "start", rmrr.read<Dmar_rmrr::Base>());
|
||||
|
@ -31,7 +31,8 @@ namespace Ahci {
|
||||
|
||||
struct Protocol;
|
||||
struct Port;
|
||||
struct Port_base;
|
||||
template <size_t> struct Port_base_tpl;
|
||||
using Port_base = Port_base_tpl<0x28>;
|
||||
struct Hba;
|
||||
|
||||
using Response = Block::Request_stream::Response;
|
||||
@ -42,10 +43,10 @@ namespace Ahci {
|
||||
/**
|
||||
* HBA definitions
|
||||
*/
|
||||
struct Ahci::Hba : private Platform::Device::Mmio
|
||||
struct Ahci::Hba : private Platform::Device::Mmio<0x28>
|
||||
{
|
||||
using Platform::Device::Mmio::base;
|
||||
using Index = Platform::Device::Mmio::Index;
|
||||
using Platform::Device::Mmio<SIZE>::base;
|
||||
using Index = Platform::Device::Mmio<SIZE>::Index;
|
||||
|
||||
Platform::Device::Irq _irq;
|
||||
|
||||
@ -85,7 +86,7 @@ struct Ahci::Hba : private Platform::Device::Mmio
|
||||
Signal_context_capability cap,
|
||||
Platform::Connection & platform)
|
||||
:
|
||||
Platform::Device::Mmio(dev, _mmio_index(platform)),
|
||||
Platform::Device::Mmio<SIZE>(dev, _mmio_index(platform)),
|
||||
_irq(dev)
|
||||
{
|
||||
log("version: "
|
||||
@ -144,6 +145,8 @@ struct Ahci::Hba : private Platform::Device::Mmio
|
||||
|
||||
/**
|
||||
* Ports implemented
|
||||
*
|
||||
* Each bit set here corresponds to a port that can be accessed by software
|
||||
*/
|
||||
struct Pi : Register<0xc, 32> { };
|
||||
|
||||
@ -176,6 +179,8 @@ struct Ahci::Hba : private Platform::Device::Mmio
|
||||
/* clear status register */
|
||||
ack_irq();
|
||||
}
|
||||
|
||||
Byte_range_ptr range_at(off_t offset) const { return Platform::Device::Mmio<SIZE>::range_at(offset); }
|
||||
};
|
||||
|
||||
|
||||
@ -185,7 +190,7 @@ struct Ahci::Hba : private Platform::Device::Mmio
|
||||
|
||||
namespace Ahci {
|
||||
|
||||
struct Device_fis : Mmio
|
||||
struct Device_fis : Mmio<0x4>
|
||||
{
|
||||
struct Status : Register<0x2, 8>
|
||||
{
|
||||
@ -194,12 +199,12 @@ namespace Ahci {
|
||||
};
|
||||
struct Error : Register<0x3, 8> { };
|
||||
|
||||
Device_fis(addr_t recv_base)
|
||||
: Mmio(recv_base + 0x40) { }
|
||||
Device_fis(Byte_range_ptr const &recv_range)
|
||||
: Mmio({recv_range.start + 0x40, recv_range.num_bytes - 0x40}) { }
|
||||
};
|
||||
|
||||
|
||||
struct Command_fis : Mmio
|
||||
struct Command_fis : Mmio<0xe>
|
||||
{
|
||||
struct Type : Register<0x0, 8> { }; /* FIS type */
|
||||
struct Bits : Register<0x1, 8, 1>
|
||||
@ -236,8 +241,8 @@ namespace Ahci {
|
||||
struct Sector8_15 : Register<0xd, 8> { };
|
||||
struct Sector : Bitset_2<Sector0_7, Sector8_15> { }; /* sector count */
|
||||
|
||||
Command_fis(addr_t base)
|
||||
: Mmio(base)
|
||||
Command_fis(Byte_range_ptr const &range)
|
||||
: Mmio(range)
|
||||
{
|
||||
clear();
|
||||
|
||||
@ -310,7 +315,7 @@ namespace Ahci {
|
||||
/**
|
||||
* AHCI command list structure header
|
||||
*/
|
||||
struct Command_header : Mmio
|
||||
struct Command_header : Mmio<0x10>
|
||||
{
|
||||
struct Bits : Register<0x0, 16>
|
||||
{
|
||||
@ -326,7 +331,7 @@ namespace Ahci {
|
||||
struct Ctba0 : Register<0x8, 32> { }; /* command table base addr (low) */
|
||||
struct Ctba0_u0 : Register<0xc, 32> { }; /* command table base addr (upper) */
|
||||
|
||||
Command_header(addr_t base) : Mmio(base) { }
|
||||
using Mmio::Mmio;
|
||||
|
||||
void cmd_table_base(addr_t base_phys)
|
||||
{
|
||||
@ -354,7 +359,7 @@ namespace Ahci {
|
||||
/**
|
||||
* ATAPI packet 12 or 16 bytes
|
||||
*/
|
||||
struct Atapi_command : Mmio
|
||||
struct Atapi_command : Mmio<0xa>
|
||||
{
|
||||
struct Command : Register<0, 8> { };
|
||||
|
||||
@ -372,9 +377,9 @@ namespace Ahci {
|
||||
struct Sector : Bitset_2<Sector0_7, Sector8_15> { };
|
||||
|
||||
|
||||
Atapi_command(addr_t base) : Mmio(base)
|
||||
Atapi_command(Byte_range_ptr const &range) : Mmio(range)
|
||||
{
|
||||
memset((void *)base, 0, 16);
|
||||
memset((void *)base(), 0, 16);
|
||||
}
|
||||
|
||||
void read_capacity()
|
||||
@ -410,7 +415,7 @@ namespace Ahci {
|
||||
/**
|
||||
* Physical region descritpor table
|
||||
*/
|
||||
struct Prdt : Mmio
|
||||
struct Prdt : Mmio<0x10>
|
||||
{
|
||||
struct Dba : Register<0x0, 32> { }; /* data base address */
|
||||
struct Dbau : Register<0x4, 32> { }; /* data base address upper 32 bits */
|
||||
@ -421,8 +426,8 @@ namespace Ahci {
|
||||
struct Irq : Bitfield<31,1> { }; /* interrupt completion */
|
||||
};
|
||||
|
||||
Prdt(addr_t base, addr_t phys, size_t bytes)
|
||||
: Mmio(base)
|
||||
Prdt(Byte_range_ptr const &range, addr_t phys, size_t bytes)
|
||||
: Mmio(range)
|
||||
{
|
||||
uint64_t addr = phys;
|
||||
write<Dba>((uint32_t)addr);
|
||||
@ -442,11 +447,14 @@ namespace Ahci {
|
||||
/* in Genode we only need one PRD (for one packet) */
|
||||
Prdt prdt;
|
||||
|
||||
Command_table(addr_t base,
|
||||
enum { ATAPI_CMD_OFF = 0x40 };
|
||||
enum { PRDT_OFF = 0x80 };
|
||||
|
||||
Command_table(Byte_range_ptr const &range,
|
||||
addr_t phys,
|
||||
size_t bytes = 0)
|
||||
: fis(base), atapi_cmd(base + 0x40),
|
||||
prdt(base + 0x80, phys, bytes)
|
||||
: fis(range), atapi_cmd({range.start + ATAPI_CMD_OFF, range.num_bytes - ATAPI_CMD_OFF}),
|
||||
prdt({range.start + PRDT_OFF, range.num_bytes - PRDT_OFF}, phys, bytes)
|
||||
{ }
|
||||
|
||||
static constexpr size_t size() { return 0x100; }
|
||||
@ -456,8 +464,11 @@ namespace Ahci {
|
||||
/**
|
||||
* Minimalistic AHCI port structure to merely detect device signature
|
||||
*/
|
||||
struct Ahci::Port_base : Mmio
|
||||
template <Genode::size_t SIZE>
|
||||
struct Ahci::Port_base_tpl : Mmio<SIZE>
|
||||
{
|
||||
using Base = Mmio<SIZE>;
|
||||
|
||||
/* device signature */
|
||||
enum Signature {
|
||||
ATA_SIG = 0x101,
|
||||
@ -468,31 +479,26 @@ struct Ahci::Port_base : Mmio
|
||||
unsigned index { };
|
||||
Platform::Connection &plat;
|
||||
Hba &hba;
|
||||
Mmio::Delayer &delayer;
|
||||
Base::Delayer &delayer;
|
||||
|
||||
/**
|
||||
* Port signature
|
||||
*/
|
||||
struct Sig : Register<0x24, 32> { };
|
||||
struct Sig : Base::template Register<0x24, 32> { };
|
||||
|
||||
static constexpr addr_t offset() { return 0x100; }
|
||||
static constexpr size_t size() { return 0x80; }
|
||||
|
||||
Port_base(unsigned index, Platform::Connection &plat, Hba &hba,
|
||||
Mmio::Delayer &delayer)
|
||||
: Mmio(hba.base() + offset() + (index * size())),
|
||||
Port_base_tpl(unsigned index, Platform::Connection &plat, Hba &hba,
|
||||
Base::Delayer &delayer)
|
||||
: Base(hba.range_at(offset() + (index * size()))),
|
||||
index(index), plat(plat), hba(hba), delayer(delayer) { }
|
||||
|
||||
bool implemented() const
|
||||
{
|
||||
return hba.port_implemented(index);
|
||||
}
|
||||
|
||||
bool ata() const { return read<Sig>() == ATA_SIG; }
|
||||
bool ata() const { return Base::template read<Sig>() == ATA_SIG; }
|
||||
|
||||
bool atapi() const
|
||||
{
|
||||
unsigned sig = read<Sig>();
|
||||
unsigned sig = Base::template read<Sig>();
|
||||
return sig == ATAPI_SIG || sig == ATAPI_SIG_QEMU;
|
||||
}
|
||||
};
|
||||
@ -513,17 +519,17 @@ struct Ahci::Protocol : Interface
|
||||
/**
|
||||
* AHCI port
|
||||
*/
|
||||
struct Ahci::Port : private Port_base
|
||||
struct Ahci::Port : private Port_base_tpl<0x3c>
|
||||
{
|
||||
using Port_base::write;
|
||||
using Port_base::read;
|
||||
using Port_base::wait_for_any;
|
||||
using Port_base::wait_for;
|
||||
using Port_base::Register_set::Polling_timeout;
|
||||
using Port_base::index;
|
||||
using Port_base::hba;
|
||||
using Port_base::delayer;
|
||||
using Port_base::plat;
|
||||
using Port_base_tpl::write;
|
||||
using Port_base_tpl::read;
|
||||
using Port_base_tpl::wait_for_any;
|
||||
using Port_base_tpl::wait_for;
|
||||
using Port_base_tpl::Register_set::Polling_timeout;
|
||||
using Port_base_tpl::index;
|
||||
using Port_base_tpl::hba;
|
||||
using Port_base_tpl::delayer;
|
||||
using Port_base_tpl::plat;
|
||||
|
||||
struct Not_ready : Exception { };
|
||||
|
||||
@ -538,10 +544,10 @@ struct Ahci::Port : private Port_base
|
||||
|
||||
addr_t device_info_dma_addr = 0;
|
||||
|
||||
addr_t cmd_list = 0;
|
||||
addr_t fis_base = 0;
|
||||
addr_t cmd_table = 0;
|
||||
addr_t device_info = 0;
|
||||
Constructible<Byte_range_ptr> cmd_list { };
|
||||
Constructible<Byte_range_ptr> fis { };
|
||||
Constructible<Byte_range_ptr> cmd_table { };
|
||||
Constructible<Byte_range_ptr> device_info { };
|
||||
|
||||
Constructible<Platform::Dma_buffer> dma_buffer { };
|
||||
addr_t dma_base = 0; /* physical address of DMA memory */
|
||||
@ -549,7 +555,7 @@ struct Ahci::Port : private Port_base
|
||||
Port(Protocol &protocol, Region_map &rm, Platform::Connection & plat,
|
||||
Hba &hba, Mmio::Delayer &delayer, unsigned index)
|
||||
:
|
||||
Port_base(index, plat, hba, delayer),
|
||||
Port_base_tpl(index, plat, hba, delayer),
|
||||
protocol(protocol), rm(rm)
|
||||
{
|
||||
reset();
|
||||
@ -871,11 +877,12 @@ struct Ahci::Port : private Port_base
|
||||
{
|
||||
/* command list 1K */
|
||||
addr_t phys = device_dma.dma_addr();
|
||||
cmd_list = addr_t(device_dma.local_addr<addr_t>());
|
||||
cmd_list.construct(device_dma.local_addr<char>(), device_dma.size());
|
||||
command_list_base(phys);
|
||||
|
||||
/* receive FIS base 256 byte */
|
||||
fis_base = cmd_list + 1024;
|
||||
enum { FIS_OFF = 1024 };
|
||||
fis.construct(cmd_list->start + FIS_OFF, cmd_list->num_bytes - FIS_OFF);
|
||||
|
||||
/*
|
||||
* Set fis receive base, clear Fre (FIS receive) before and wait for FR
|
||||
@ -886,28 +893,31 @@ struct Ahci::Port : private Port_base
|
||||
fis_rcv_base(phys + 1024);
|
||||
|
||||
/* command table */
|
||||
cmd_table = addr_t(cmd_dma.local_addr<addr_t>());
|
||||
cmd_table.construct(cmd_dma.local_addr<char>(), cmd_dma.size());
|
||||
phys = cmd_dma.dma_addr();
|
||||
|
||||
/* set command table addresses in command list */
|
||||
for (unsigned i = 0; i < cmd_slots; i++) {
|
||||
Command_header h(cmd_list + (i * Command_header::size()));
|
||||
off_t off = (i * Command_header::size());
|
||||
Command_header h({cmd_list->start + off, cmd_list->num_bytes - off});
|
||||
h.cmd_table_base(phys + (i * Command_table::size()));
|
||||
}
|
||||
|
||||
/* dataspace for device info */
|
||||
device_info_dma_addr = device_info_dma.dma_addr();
|
||||
device_info = addr_t(device_info_dma.local_addr<addr_t>());
|
||||
device_info.construct(device_info_dma.local_addr<char>(), device_info_dma.size());
|
||||
}
|
||||
|
||||
addr_t command_table_addr(unsigned slot)
|
||||
Byte_range_ptr command_table_range(unsigned slot)
|
||||
{
|
||||
return cmd_table + (slot * Command_table::size());
|
||||
off_t off = slot * Command_table::size();
|
||||
return {cmd_table->start + off, cmd_table->num_bytes - off};
|
||||
};
|
||||
|
||||
addr_t command_header_addr(unsigned slot)
|
||||
Byte_range_ptr command_header_range(unsigned slot)
|
||||
{
|
||||
return cmd_list + (slot * Command_header::size());
|
||||
off_t off = slot * Command_header::size();
|
||||
return {cmd_list->start + off, cmd_list->num_bytes - off};
|
||||
}
|
||||
|
||||
void execute(unsigned slot)
|
||||
|
@ -29,9 +29,9 @@ namespace Ata {
|
||||
/**
|
||||
* Return data of 'identify_device' ATA command
|
||||
*/
|
||||
struct Ata::Identity : Mmio
|
||||
struct Ata::Identity : Mmio<0x1a4>
|
||||
{
|
||||
Identity(addr_t base) : Mmio(base) { }
|
||||
using Mmio::Mmio;
|
||||
|
||||
struct Serial_number : Register_array<0x14, 8, 20, 8> { };
|
||||
struct Model_number : Register_array<0x36, 8, 40, 8> { };
|
||||
@ -222,7 +222,7 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||
unsigned init(Port &port) override
|
||||
{
|
||||
/* identify device */
|
||||
Command_table table(port.command_table_addr(0),
|
||||
Command_table table(port.command_table_range(0),
|
||||
port.device_info_dma_addr, 0x1000);
|
||||
table.fis.identify_device();
|
||||
port.execute(0);
|
||||
@ -231,7 +231,7 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||
Port::Is::Pss::Equal(1),
|
||||
Port::Is::Dhrs::Equal(1));
|
||||
|
||||
_identity.construct(port.device_info);
|
||||
_identity.construct(*port.device_info);
|
||||
serial.construct(*_identity);
|
||||
model.construct(*_identity);
|
||||
|
||||
@ -316,7 +316,7 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||
_slot_states |= 1u << slot;
|
||||
|
||||
/* setup fis */
|
||||
Command_table table(port.command_table_addr(slot),
|
||||
Command_table table(port.command_table_range(slot),
|
||||
port.dma_base + request.offset, /* physical address */
|
||||
op.count * _block_size());
|
||||
|
||||
@ -335,7 +335,7 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||
}
|
||||
|
||||
/* set or clear write flag in command header */
|
||||
Command_header header(port.command_header_addr(slot));
|
||||
Command_header header(port.command_header_range(slot));
|
||||
header.write<Command_header::Bits::W>(write ? 1 : 0);
|
||||
header.clear_byte_count();
|
||||
|
||||
|
@ -33,7 +33,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
|
||||
void _atapi_command(Port &port)
|
||||
{
|
||||
Command_header header(port.command_header_addr(0));
|
||||
Command_header header(port.command_header_range(0));
|
||||
header.atapi_command();
|
||||
header.clear_byte_count();
|
||||
port.execute(0);
|
||||
@ -41,7 +41,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
|
||||
void _read_sense(Port &port)
|
||||
{
|
||||
Command_table table(port.command_table_addr(0),
|
||||
Command_table table(port.command_table_range(0),
|
||||
port.device_info_dma_addr, 0x1000);
|
||||
table.fis.atapi();
|
||||
table.atapi_cmd.read_sense();
|
||||
@ -51,7 +51,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
|
||||
void _test_unit_ready(Port &port)
|
||||
{
|
||||
Command_table table(port.command_table_addr(0), 0, 0);
|
||||
Command_table table(port.command_table_range(0), 0, 0);
|
||||
table.fis.atapi();
|
||||
table.atapi_cmd.test_unit_ready();
|
||||
|
||||
@ -60,7 +60,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
|
||||
void _read_capacity(Port &port)
|
||||
{
|
||||
Command_table table(port.command_table_addr(0),
|
||||
Command_table table(port.command_table_range(0),
|
||||
port.device_info_dma_addr, 0x1000);
|
||||
table.fis.atapi();
|
||||
table.fis.byte_count(~0);
|
||||
@ -72,7 +72,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
|
||||
void _start_unit(Port &port)
|
||||
{
|
||||
Command_table table(port.command_table_addr(0), 0, 0);
|
||||
Command_table table(port.command_table_range(0), 0, 0);
|
||||
table.fis.atapi();
|
||||
table.atapi_cmd.start_unit();
|
||||
|
||||
@ -110,7 +110,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
port.wait_for(port.delayer, Port::Is::Dhrs::Equal(1));
|
||||
port.ack_irq();
|
||||
|
||||
Device_fis f(port.fis_base);
|
||||
Device_fis f(*port.fis);
|
||||
/* check if devic is ready */
|
||||
if (!f.read<Device_fis::Status::Device_ready>() || f.read<Device_fis::Error>())
|
||||
throw Port::Polling_timeout();
|
||||
@ -121,8 +121,8 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
Port::Is::Dhrs::Equal(1));
|
||||
port.ack_irq();
|
||||
|
||||
_block_count = host_to_big_endian(((unsigned *)port.device_info)[0]) + 1;
|
||||
_block_size = host_to_big_endian(((unsigned *)port.device_info)[1]);
|
||||
_block_count = host_to_big_endian(((unsigned *)port.device_info->start)[0]) + 1;
|
||||
_block_size = host_to_big_endian(((unsigned *)port.device_info->start)[1]);
|
||||
},
|
||||
[&] {}, 3);
|
||||
|
||||
@ -158,7 +158,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
_pending.success = false;
|
||||
|
||||
/* setup fis */
|
||||
Command_table table(port.command_table_addr(0),
|
||||
Command_table table(port.command_table_range(0),
|
||||
port.dma_base + request.offset,
|
||||
op.count * _block_size);
|
||||
table.fis.atapi();
|
||||
@ -168,7 +168,7 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||
table.fis.byte_count(~0);
|
||||
|
||||
/* set and clear write flag in command header */
|
||||
Command_header header(port.command_header_addr(0));
|
||||
Command_header header(port.command_header_range(0));
|
||||
header.write<Command_header::Bits::W>(0);
|
||||
header.clear_byte_count();
|
||||
|
||||
|
@ -53,7 +53,7 @@ class Ahci::Driver : Noncopyable
|
||||
Dispatch &_dispatch;
|
||||
|
||||
|
||||
struct Timer_delayer : Mmio::Delayer, Timer::Connection
|
||||
struct Timer_delayer : Mmio<0>::Delayer, Timer::Connection
|
||||
{
|
||||
using Timer::Connection::Connection;
|
||||
|
||||
@ -78,11 +78,11 @@ class Ahci::Driver : Noncopyable
|
||||
|
||||
for (unsigned index = 0; index < MAX_PORTS; index++) {
|
||||
|
||||
Port_base port(index, _plat, _hba, _delayer);
|
||||
|
||||
if (port.implemented() == false)
|
||||
if (_hba.port_implemented(index) == false)
|
||||
continue;
|
||||
|
||||
Port_base port(index, _plat, _hba, _delayer);
|
||||
|
||||
bool enabled = false;
|
||||
if (port.ata()) {
|
||||
try {
|
||||
|
@ -86,12 +86,12 @@ struct Pl11x_driver::Main
|
||||
|
||||
using Type = Platform::Device::Type;
|
||||
|
||||
Platform::Connection _platform { _env };
|
||||
Platform::Device _pl11x_dev { _platform, Type { "arm,pl111" } };
|
||||
Platform::Device _sp810_dev { _platform, Type { "arm,sp810" } };
|
||||
Platform::Device::Mmio _lcd_io_mem { _pl11x_dev };
|
||||
Platform::Device::Mmio _sys_mem { _sp810_dev };
|
||||
Platform::Dma_buffer _fb_dma { _platform, FRAMEBUFFER_SIZE, UNCACHED };
|
||||
Platform::Connection _platform { _env };
|
||||
Platform::Device _pl11x_dev { _platform, Type { "arm,pl111" } };
|
||||
Platform::Device _sp810_dev { _platform, Type { "arm,sp810" } };
|
||||
Platform::Device::Mmio<0> _lcd_io_mem { _pl11x_dev };
|
||||
Platform::Device::Mmio<0> _sys_mem { _sp810_dev };
|
||||
Platform::Dma_buffer _fb_dma { _platform, FRAMEBUFFER_SIZE, UNCACHED };
|
||||
|
||||
void _init_device();
|
||||
|
||||
|
@ -37,16 +37,14 @@ class Main
|
||||
** Qemu firmware interface **
|
||||
*****************************/
|
||||
|
||||
struct Fw : Mmio
|
||||
struct Fw : Mmio<0x18>
|
||||
{
|
||||
template <typename T>
|
||||
struct Data : Register<0x0, sizeof(T) * 8> { };
|
||||
struct Selector : Register<0x8, 16> { };
|
||||
struct Dma : Register<0x10, 64> { };
|
||||
|
||||
Fw(addr_t const base)
|
||||
:
|
||||
Mmio(base) { }
|
||||
Fw(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
Env &_env;
|
||||
@ -57,10 +55,10 @@ class Main
|
||||
|
||||
using Type = Platform::Device::Type;
|
||||
|
||||
Platform::Connection _platform { _env };
|
||||
Platform::Device _fw_dev { _platform, Type { "qemu,fw-cfg-mmio" } };
|
||||
Platform::Device::Mmio _fw_mem { _fw_dev };
|
||||
Fw _fw { (addr_t)_fw_mem.local_addr<addr_t>() };
|
||||
Platform::Connection _platform { _env };
|
||||
Platform::Device _fw_dev { _platform, Type { "qemu,fw-cfg-mmio" } };
|
||||
Platform::Device::Mmio<0> _fw_mem { _fw_dev };
|
||||
Fw _fw { {_fw_mem.local_addr<char>(), _fw_mem.size()} };
|
||||
|
||||
Platform::Dma_buffer _fb_dma { _platform, SCR_HEIGHT * SCR_STRIDE, UNCACHED };
|
||||
Platform::Dma_buffer _config_dma { _platform, 0x1000, UNCACHED };
|
||||
@ -91,15 +89,13 @@ class Main
|
||||
return host_to_big_endian(_fw.read<Fw::Data<T>>()); }
|
||||
|
||||
/* DMA control structure */
|
||||
struct Fw_dma_config : Genode::Mmio
|
||||
struct Fw_dma_config : Genode::Mmio<0x10>
|
||||
{
|
||||
struct Control : Register<0x0, 32> { };
|
||||
struct Length : Register<0x4, 32> { };
|
||||
struct Address : Register<0x8, 64> { };
|
||||
|
||||
Fw_dma_config(addr_t const base)
|
||||
:
|
||||
Mmio(base)
|
||||
Fw_dma_config(Byte_range_ptr const &range) : Mmio(range)
|
||||
{
|
||||
/* set write bit */
|
||||
write<Control>(host_to_big_endian(1u << 4));
|
||||
@ -116,7 +112,7 @@ class Main
|
||||
};
|
||||
|
||||
/* ramfb configuration */
|
||||
struct Ram_fb_config : Genode::Mmio
|
||||
struct Ram_fb_config : Genode::Mmio<0x1c>
|
||||
{
|
||||
struct Address : Register<0x0, 64> { };
|
||||
struct Drm_format : Register<0x8, 32> { };
|
||||
@ -124,17 +120,15 @@ class Main
|
||||
struct Height : Register<0x14, 32> { };
|
||||
struct Stride : Register<0x18, 32> { };
|
||||
|
||||
Ram_fb_config(addr_t const base)
|
||||
:
|
||||
Mmio(base)
|
||||
{
|
||||
enum {
|
||||
DRM_FORMAT_ARGB8888 = 0x34325241,
|
||||
};
|
||||
/* RGBA32 */
|
||||
write<Drm_format>(host_to_big_endian(DRM_FORMAT_ARGB8888));
|
||||
write<Stride>(host_to_big_endian(SCR_STRIDE));
|
||||
}
|
||||
Ram_fb_config(Byte_range_ptr const &range) : Mmio(range)
|
||||
{
|
||||
enum {
|
||||
DRM_FORMAT_ARGB8888 = 0x34325241,
|
||||
};
|
||||
/* RGBA32 */
|
||||
write<Drm_format>(host_to_big_endian(DRM_FORMAT_ARGB8888));
|
||||
write<Stride>(host_to_big_endian(SCR_STRIDE));
|
||||
}
|
||||
};
|
||||
|
||||
Fw_config_file _find_ramfb()
|
||||
@ -173,12 +167,12 @@ class Main
|
||||
addr_t config_phys = _config_dma.dma_addr();
|
||||
addr_t fb_phys = _fb_dma.dma_addr();
|
||||
|
||||
Ram_fb_config config { config_addr };
|
||||
Ram_fb_config config { {(char *)config_addr, _config_dma.size()} };
|
||||
config.write<Ram_fb_config::Address>(host_to_big_endian(fb_phys));
|
||||
config.write<Ram_fb_config::Width>(host_to_big_endian(SCR_WIDTH));
|
||||
config.write<Ram_fb_config::Height>(host_to_big_endian(SCR_HEIGHT));
|
||||
|
||||
Fw_dma_config fw_dma { config_addr + FW_OFFSET};
|
||||
Fw_dma_config fw_dma { {(char *)config_addr + FW_OFFSET, _config_dma.size() - FW_OFFSET} };
|
||||
fw_dma.write<Fw_dma_config::Length>(host_to_big_endian(file.size));
|
||||
fw_dma.write<Fw_dma_config::Address>(host_to_big_endian(config_phys));
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace Gpio {
|
||||
class Reg;
|
||||
}
|
||||
|
||||
class Gpio::Reg : Attached_io_mem_dataspace, Mmio
|
||||
class Gpio::Reg : Attached_io_mem_dataspace, Mmio<0xa0>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -139,7 +139,7 @@ class Gpio::Reg : Attached_io_mem_dataspace, Mmio
|
||||
addr_t base, off_t offset, size_t size)
|
||||
:
|
||||
Attached_io_mem_dataspace(env, base, size),
|
||||
Mmio((addr_t)local_addr<Reg>() + offset),
|
||||
Mmio({local_addr<char>() + offset, size - offset}),
|
||||
_delayer(env)
|
||||
{ }
|
||||
|
||||
|
@ -25,9 +25,11 @@
|
||||
|
||||
namespace Igd {
|
||||
|
||||
using Genode::Byte_range_ptr;
|
||||
|
||||
struct Context_status_qword;
|
||||
|
||||
struct Common_context_regs;
|
||||
template <size_t> struct Common_context_regs;
|
||||
|
||||
struct Generation;
|
||||
|
||||
@ -84,27 +86,30 @@ struct Igd::Context_status_qword : Genode::Register<64>
|
||||
};
|
||||
|
||||
|
||||
struct Igd::Common_context_regs : public Genode::Mmio
|
||||
template <Genode::size_t SIZE>
|
||||
struct Igd::Common_context_regs : public Genode::Mmio<SIZE>
|
||||
{
|
||||
using Base = Genode::Mmio<SIZE>;
|
||||
|
||||
template <long int OFFSET>
|
||||
struct Common_register : Register<OFFSET * sizeof(uint32_t), 32> { };
|
||||
struct Common_register : Base::template Register<OFFSET * sizeof(uint32_t), 32> { };
|
||||
|
||||
template <long int OFFSET, size_t NUM>
|
||||
struct Common_register_array : Register_array<OFFSET * sizeof(uint32_t), 32, NUM, 32> { };
|
||||
struct Common_register_array : Base::template Register_array<OFFSET * sizeof(uint32_t), 32, NUM, 32> { };
|
||||
|
||||
template <long int OFFSET, size_t NUM>
|
||||
struct Common_register_array_64 : Register_array<OFFSET * sizeof(uint32_t), 64, NUM, 64> { };
|
||||
struct Common_register_array_64 : Base::template Register_array<OFFSET * sizeof(uint32_t), 64, NUM, 64> { };
|
||||
|
||||
addr_t _base;
|
||||
Byte_range_ptr _range;
|
||||
|
||||
Common_context_regs(addr_t base) : Genode::Mmio(base), _base(base) { }
|
||||
Common_context_regs(Byte_range_ptr const &range) : Genode::Mmio<SIZE>(range), _range(range.start, range.num_bytes) { }
|
||||
|
||||
addr_t base() const { return _base; }
|
||||
addr_t base() const { return (addr_t)_range.start; }
|
||||
|
||||
template <typename T>
|
||||
void write_offset(typename T::access_t const value)
|
||||
{
|
||||
write<T>(value + T::OFFSET);
|
||||
Base::template write<T>(value + T::OFFSET);
|
||||
}
|
||||
};
|
||||
|
||||
@ -118,7 +123,7 @@ struct Igd::Common_context_regs : public Genode::Mmio
|
||||
* All engines use the same layout until offset 0x118.
|
||||
*/
|
||||
template <Genode::addr_t RING_BASE>
|
||||
class Igd::Execlist_context : public Igd::Common_context_regs
|
||||
class Igd::Execlist_context : public Igd::Common_context_regs<0x1E * sizeof(uint32_t) + 2 * 4>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -360,7 +365,7 @@ class Igd::Execlist_context : public Igd::Common_context_regs
|
||||
|
||||
public:
|
||||
|
||||
Execlist_context(addr_t const base) : Common_context_regs(base) { }
|
||||
Execlist_context(Byte_range_ptr const &range) : Common_context_regs(range) { }
|
||||
|
||||
void setup(addr_t const ring_buffer_start,
|
||||
size_t const ring_buffer_length,
|
||||
@ -461,7 +466,7 @@ class Igd::Execlist_context : public Igd::Common_context_regs
|
||||
|
||||
|
||||
template <Genode::addr_t RING_BASE>
|
||||
class Igd::Ppgtt_context : public Igd::Common_context_regs
|
||||
class Igd::Ppgtt_context : public Igd::Common_context_regs<0x47 * sizeof(uint32_t) + 9 * 4>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -596,7 +601,7 @@ class Igd::Ppgtt_context : public Igd::Common_context_regs
|
||||
|
||||
public:
|
||||
|
||||
Ppgtt_context(addr_t const base) : Common_context_regs(base) { }
|
||||
Ppgtt_context(Byte_range_ptr const &range) : Common_context_regs(range) { }
|
||||
|
||||
void setup(uint64_t const plm4_addr)
|
||||
{
|
||||
@ -678,7 +683,7 @@ class Igd::Urb_atomic_context
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2d-11.15 p. 199
|
||||
*/
|
||||
class Igd::Hardware_status_page : public Igd::Common_context_regs
|
||||
class Igd::Hardware_status_page : public Igd::Common_context_regs<0x32*4 + 4>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -708,8 +713,8 @@ class Igd::Hardware_status_page : public Igd::Common_context_regs
|
||||
struct Context_status_dwords : Common_register_array_64<16, CONTEXT_STATUS_REGISTERS> { };
|
||||
struct Last_written_status_offset : Common_register<31> { };
|
||||
|
||||
Hardware_status_page(addr_t base)
|
||||
: Common_context_regs(base)
|
||||
Hardware_status_page(Byte_range_ptr const &range)
|
||||
: Common_context_regs(range)
|
||||
{
|
||||
semaphore(0);
|
||||
}
|
||||
@ -784,14 +789,14 @@ class Igd::Hardware_status_page : public Igd::Common_context_regs
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2d-11.15 p. 303
|
||||
*/
|
||||
class Igd::Pphardware_status_page : public Igd::Common_context_regs
|
||||
class Igd::Pphardware_status_page : public Igd::Common_context_regs<4 * 4 + 4>
|
||||
{
|
||||
public:
|
||||
|
||||
struct Ring_head_ptr_storage : Common_register<4> { };
|
||||
|
||||
Pphardware_status_page(addr_t base)
|
||||
: Common_context_regs(base) { }
|
||||
Pphardware_status_page(Byte_range_ptr const &range)
|
||||
: Common_context_regs(range) { }
|
||||
};
|
||||
|
||||
|
||||
@ -848,11 +853,11 @@ class Igd::Rcs_context
|
||||
|
||||
public:
|
||||
|
||||
Rcs_context(addr_t const map_base)
|
||||
Rcs_context(Byte_range_ptr const &map_range)
|
||||
:
|
||||
_hw_status_page (map_base),
|
||||
_execlist_context(map_base + HW_STATUS_PAGE_SIZE),
|
||||
_ppgtt_context (map_base + HW_STATUS_PAGE_SIZE)
|
||||
_hw_status_page (map_range),
|
||||
_execlist_context({map_range.start + HW_STATUS_PAGE_SIZE, map_range.num_bytes - HW_STATUS_PAGE_SIZE}),
|
||||
_ppgtt_context ({map_range.start + HW_STATUS_PAGE_SIZE, map_range.num_bytes - HW_STATUS_PAGE_SIZE})
|
||||
{ }
|
||||
|
||||
void setup(addr_t const ring_buffer_start,
|
||||
|
@ -440,12 +440,12 @@ struct Igd::Device
|
||||
return offset;
|
||||
}
|
||||
|
||||
void with_vaddr(auto const &fn) const
|
||||
void with_vrange(auto const &fn) const
|
||||
{
|
||||
addr_t const offset = (map.map.offset + skip) * PAGE_SIZE;
|
||||
|
||||
if (!device._resources.with_gmadr(offset, [&](auto const addr) {
|
||||
fn(addr);
|
||||
if (!device._resources.with_gmadr(offset, [&](Byte_range_ptr const &range) {
|
||||
fn(range);
|
||||
}))
|
||||
error("Gmadr object unavailable");
|
||||
}
|
||||
@ -484,8 +484,8 @@ struct Igd::Device
|
||||
|
||||
void with_context(auto const &fn)
|
||||
{
|
||||
ctx.with_vaddr([&](auto const vaddr) {
|
||||
auto context = CONTEXT(vaddr);
|
||||
ctx.with_vrange([&](Byte_range_ptr const &vrange) {
|
||||
auto context = CONTEXT(vrange);
|
||||
|
||||
fn(context);
|
||||
});
|
||||
@ -493,8 +493,8 @@ struct Igd::Device
|
||||
|
||||
void with_context_ring(auto const &fn)
|
||||
{
|
||||
ctx.with_vaddr([&](auto const vaddr) {
|
||||
auto context = CONTEXT(vaddr);
|
||||
ctx.with_vrange([&](Byte_range_ptr const &vrange) {
|
||||
auto context = CONTEXT(vrange);
|
||||
|
||||
fn(context, _ring);
|
||||
});
|
||||
@ -1247,9 +1247,9 @@ struct Igd::Device
|
||||
if (!_hw_status_ctx.constructed())
|
||||
_hw_status_ctx.construct(_md_alloc, *this, 1, 0);
|
||||
if (!_hw_status_page.constructed()) {
|
||||
/* global hw_status_ctx becomes never invalid up to now, so using vaddr is ok */
|
||||
_hw_status_ctx->with_vaddr([&](auto const vaddr) {
|
||||
_hw_status_page.construct(vaddr);
|
||||
/* global hw_status_ctx becomes never invalid up to now, so using vrange is ok */
|
||||
_hw_status_ctx->with_vrange([&](Byte_range_ptr const &vrange) {
|
||||
_hw_status_page.construct(vrange);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,15 @@
|
||||
#include <types.h>
|
||||
|
||||
|
||||
namespace Igd { class Mmio; }
|
||||
namespace Igd {
|
||||
|
||||
static constexpr size_t MMIO_SIZE = 0x190074;
|
||||
|
||||
class Mmio;
|
||||
}
|
||||
|
||||
|
||||
class Igd::Mmio : public Platform::Device::Mmio
|
||||
class Igd::Mmio : public Platform::Device::Mmio<MMIO_SIZE>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -1137,7 +1142,7 @@ class Igd::Mmio : public Platform::Device::Mmio
|
||||
|
||||
private:
|
||||
|
||||
struct Timer_delayer : Genode::Mmio::Delayer
|
||||
struct Timer_delayer : Genode::Mmio<MMIO_SIZE>::Delayer
|
||||
{
|
||||
Timer::Connection _timer;
|
||||
Timer_delayer(Genode::Env & env) : _timer(env) { }
|
||||
@ -1666,7 +1671,7 @@ class Igd::Mmio : public Platform::Device::Mmio
|
||||
public:
|
||||
|
||||
Mmio(Platform::Device & device, Genode::Env & env)
|
||||
: Platform::Device::Mmio(device, {0}), _delayer(env) { }
|
||||
: Platform::Device::Mmio<MMIO_SIZE>(device, {0}), _delayer(env) { }
|
||||
|
||||
Delayer &delayer() { return _delayer; }
|
||||
|
||||
|
@ -284,15 +284,14 @@ class Platform::Resources : Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
Env & _env;
|
||||
Signal_context_capability const _irq_cap;
|
||||
Platform::Connection _platform { _env };
|
||||
|
||||
Reconstructible<Platform::Device> _device { _platform };
|
||||
Reconstructible<Platform::Device::Irq> _irq { *_device };
|
||||
Reconstructible<Igd::Mmio> _mmio { *_device, _env };
|
||||
Reconstructible<Platform::Device::Mmio> _gmadr { *_device, Platform::Device::Mmio::Index(1) };
|
||||
Reconstructible<Attached_dataspace> _gmadr_mem { _env.rm(), _gmadr->cap() };
|
||||
Env & _env;
|
||||
Signal_context_capability const _irq_cap;
|
||||
Platform::Connection _platform { _env };
|
||||
Reconstructible<Platform::Device> _device { _platform };
|
||||
Reconstructible<Platform::Device::Irq> _irq { *_device };
|
||||
Reconstructible<Igd::Mmio> _mmio { *_device, _env };
|
||||
Reconstructible<Platform::Device::Mmio<0> > _gmadr { *_device, Platform::Device::Mmio<0>::Index(1) };
|
||||
Reconstructible<Attached_dataspace> _gmadr_mem { _env.rm(), _gmadr->cap() };
|
||||
|
||||
Region_map_client _rm_gttmm;
|
||||
Region_map_client _rm_gmadr;
|
||||
@ -384,13 +383,10 @@ class Platform::Resources : Noncopyable
|
||||
__attribute__((warn_unused_result))
|
||||
bool with_gmadr(auto const offset, auto const &fn)
|
||||
{
|
||||
if (!_gmadr_mem.constructed())
|
||||
if (!_gmadr.constructed() || !_gmadr_mem.constructed())
|
||||
return false;
|
||||
|
||||
auto const addr = reinterpret_cast<addr_t>(_gmadr_mem->local_addr<addr_t>())
|
||||
+ offset;
|
||||
fn(addr);
|
||||
|
||||
fn({_gmadr_mem->local_addr<char>() + offset, _gmadr->size() - offset });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,10 @@ class Igd::Ring_buffer
|
||||
Index _head { };
|
||||
|
||||
void with_dwords(auto const &fn) const {
|
||||
_memory.with_vaddr([&](auto vaddr) { fn((uint32_t *)vaddr); }); }
|
||||
_memory.with_vrange([&](Byte_range_ptr const &vrange) { fn((uint32_t *)vrange.start); }); }
|
||||
|
||||
void with_dwords(auto const &fn) {
|
||||
_memory.with_vaddr([&](auto vaddr) { fn((uint32_t *)vaddr); }); }
|
||||
_memory.with_vrange([&](Byte_range_ptr const &vrange) { fn((uint32_t *)vrange.start); }); }
|
||||
|
||||
public:
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace I2c { struct Mmio; }
|
||||
|
||||
|
||||
struct I2c::Mmio: Platform::Device::Mmio
|
||||
struct I2c::Mmio: Platform::Device::Mmio<0x12>
|
||||
{
|
||||
struct Address : Mmio::Register<0x0, 16> {
|
||||
struct Adr : Mmio::Register<0x0, 16>::Bitfield<1, 7> {};
|
||||
@ -49,7 +49,7 @@ struct I2c::Mmio: Platform::Device::Mmio
|
||||
|
||||
struct Data : Mmio::Register<0x10, 16> {};
|
||||
|
||||
Mmio(Platform::Device &device) : Platform::Device::Mmio { device } { }
|
||||
Mmio(Platform::Device &device) : Platform::Device::Mmio<SIZE> { device } { }
|
||||
};
|
||||
|
||||
#endif /* _I2C_MMIO_H_ */
|
||||
|
@ -94,7 +94,7 @@ class Lan9118_base
|
||||
{ }
|
||||
};
|
||||
|
||||
Platform::Device::Mmio &_mmio;
|
||||
Platform::Device::Mmio<0> &_mmio;
|
||||
Platform::Device::Irq &_irq;
|
||||
volatile uint32_t *_reg_base { _mmio.local_addr<uint32_t>() };
|
||||
Timer::Connection _timer;
|
||||
@ -281,10 +281,10 @@ class Lan9118_base
|
||||
*/
|
||||
class Device_not_supported { };
|
||||
|
||||
Lan9118_base(Platform::Device::Mmio &mmio,
|
||||
Platform::Device::Irq &irq,
|
||||
Signal_context_capability irq_handler,
|
||||
Env &env)
|
||||
Lan9118_base(Platform::Device::Mmio<0> &mmio,
|
||||
Platform::Device::Irq &irq,
|
||||
Signal_context_capability irq_handler,
|
||||
Env &env)
|
||||
:
|
||||
_mmio(mmio), _irq(irq), _timer(env)
|
||||
{
|
||||
@ -441,10 +441,10 @@ class Uplink_client : public Signal_handler<Uplink_client>,
|
||||
|
||||
public:
|
||||
|
||||
Uplink_client(Env &env,
|
||||
Allocator &alloc,
|
||||
Platform::Device::Mmio &mmio,
|
||||
Platform::Device::Irq &irq)
|
||||
Uplink_client(Env &env,
|
||||
Allocator &alloc,
|
||||
Platform::Device::Mmio<0> &mmio,
|
||||
Platform::Device::Irq &irq)
|
||||
:
|
||||
Signal_handler<Uplink_client> { env.ep(), *this, &Uplink_client::_handle_irq },
|
||||
Lan9118_base { mmio, irq, *this, env },
|
||||
|
@ -31,13 +31,13 @@ class Main
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Platform::Connection _platform { _env };
|
||||
Platform::Device _device { _platform };
|
||||
Platform::Device::Mmio _mmio { _device };
|
||||
Platform::Device::Irq _irq { _device };
|
||||
Uplink_client _uplink_client { _env, _heap, _mmio, _irq };
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Platform::Connection _platform { _env };
|
||||
Platform::Device _device { _platform };
|
||||
Platform::Device::Mmio<0> _mmio { _device };
|
||||
Platform::Device::Irq _irq { _device };
|
||||
Uplink_client _uplink_client { _env, _heap, _mmio, _irq };
|
||||
|
||||
public:
|
||||
|
||||
|
@ -59,12 +59,13 @@ namespace Nvme {
|
||||
|
||||
struct Cqe;
|
||||
|
||||
struct Sqe;
|
||||
template <size_t> struct Sqe;
|
||||
struct Sqe_header;
|
||||
struct Sqe_create_cq;
|
||||
struct Sqe_create_sq;
|
||||
struct Sqe_identify;
|
||||
struct Sqe_get_feature;
|
||||
struct Sqe_set_feature;
|
||||
template <size_t> struct Sqe_set_feature;
|
||||
struct Sqe_io;
|
||||
|
||||
struct Set_hmb;
|
||||
@ -165,7 +166,7 @@ namespace Nvme {
|
||||
/*
|
||||
* Identify command data
|
||||
*/
|
||||
struct Nvme::Identify_data : Genode::Mmio
|
||||
struct Nvme::Identify_data : Genode::Mmio<0x208>
|
||||
{
|
||||
enum {
|
||||
SN_OFFSET = 0x04, SN_LEN = 20,
|
||||
@ -202,10 +203,9 @@ struct Nvme::Identify_data : Genode::Mmio
|
||||
struct Nn : Register<0x204, 32> { }; /* number of namespaces */
|
||||
struct Vwc : Register<0x204, 8> { }; /* volatile write cache */
|
||||
|
||||
Identify_data(addr_t const base)
|
||||
: Genode::Mmio(base)
|
||||
Identify_data(Byte_range_ptr const &range) : Mmio(range)
|
||||
{
|
||||
char const *p = (char const*)base;
|
||||
char const *p = Mmio::range().start;
|
||||
|
||||
sn = Sn(Util::extract_string(p, SN_OFFSET, SN_LEN+1));
|
||||
mn = Mn(Util::extract_string(p, MN_OFFSET, MN_LEN+1));
|
||||
@ -217,7 +217,7 @@ struct Nvme::Identify_data : Genode::Mmio
|
||||
/*
|
||||
* Identify name space command data
|
||||
*/
|
||||
struct Nvme::Identify_ns_data : public Genode::Mmio
|
||||
struct Nvme::Identify_ns_data : public Genode::Mmio<0xc0>
|
||||
{
|
||||
struct Nsze : Register<0x00, 64> { }; /* name space size */
|
||||
struct Ncap : Register<0x08, 64> { }; /* name space capacity */
|
||||
@ -242,16 +242,14 @@ struct Nvme::Identify_ns_data : public Genode::Mmio
|
||||
struct Rp : Bitfield<24, 2> { }; /* relative performance */
|
||||
};
|
||||
|
||||
Identify_ns_data(addr_t const base)
|
||||
: Genode::Mmio(base)
|
||||
{ }
|
||||
Identify_ns_data(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Queue doorbell register
|
||||
*/
|
||||
struct Nvme::Doorbell : public Genode::Mmio
|
||||
struct Nvme::Doorbell : public Genode::Mmio<0x8>
|
||||
{
|
||||
struct Sqtdbl : Register<0x00, 32>
|
||||
{
|
||||
@ -263,15 +261,14 @@ struct Nvme::Doorbell : public Genode::Mmio
|
||||
struct Cqh : Bitfield< 0, 16> { }; /* submission queue tail */
|
||||
};
|
||||
|
||||
Doorbell(addr_t const base)
|
||||
: Genode::Mmio(base) { }
|
||||
Doorbell(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Completion queue entry
|
||||
*/
|
||||
struct Nvme::Cqe : Genode::Mmio
|
||||
struct Nvme::Cqe : Genode::Mmio<0x10>
|
||||
{
|
||||
struct Dw0 : Register<0x00, 32> { }; /* command specific */
|
||||
struct Dw1 : Register<0x04, 32> { }; /* reserved */
|
||||
@ -288,7 +285,7 @@ struct Nvme::Cqe : Genode::Mmio
|
||||
struct Dnr : Bitfield<15, 1> { }; /* do not retry */
|
||||
};
|
||||
|
||||
Cqe(addr_t const base) : Genode::Mmio(base) { }
|
||||
Cqe(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
static uint32_t request_id(Nvme::Cqe const &b)
|
||||
{
|
||||
@ -324,46 +321,53 @@ struct Nvme::Cqe : Genode::Mmio
|
||||
/*
|
||||
* Submission queue entry base
|
||||
*/
|
||||
struct Nvme::Sqe : Genode::Mmio
|
||||
template <size_t SIZE>
|
||||
struct Nvme::Sqe : Genode::Mmio<SIZE>
|
||||
{
|
||||
struct Cdw0 : Register<0x00, 32>
|
||||
using Base = Genode::Mmio<SIZE>;
|
||||
|
||||
using Cdw0_base = Base::template Register<0x00, 32>;
|
||||
struct Cdw0 : Cdw0_base
|
||||
{
|
||||
struct Opc : Bitfield< 0, 8> { }; /* opcode */
|
||||
struct Fuse : Bitfield< 9, 2> { }; /* fused operation */
|
||||
struct Psdt : Bitfield<14, 2> { }; /* PRP or SGL for data transfer */
|
||||
struct Cid : Bitfield<16, 16> { }; /* command identifier */
|
||||
struct Opc : Cdw0_base::template Bitfield< 0, 8> { }; /* opcode */
|
||||
struct Fuse : Cdw0_base::template Bitfield< 9, 2> { }; /* fused operation */
|
||||
struct Psdt : Cdw0_base::template Bitfield<14, 2> { }; /* PRP or SGL for data transfer */
|
||||
struct Cid : Cdw0_base::template Bitfield<16, 16> { }; /* command identifier */
|
||||
};
|
||||
struct Nsid : Register<0x04, 32> { };
|
||||
struct Mptr : Register<0x10, 64> { };
|
||||
struct Prp1 : Register<0x18, 64> { };
|
||||
struct Prp2 : Register<0x20, 64> { };
|
||||
struct Nsid : Base::template Register<0x04, 32> { };
|
||||
struct Mptr : Base::template Register<0x10, 64> { };
|
||||
struct Prp1 : Base::template Register<0x18, 64> { };
|
||||
struct Prp2 : Base::template Register<0x20, 64> { };
|
||||
|
||||
/* SGL not supported */
|
||||
|
||||
Sqe(addr_t const base) : Genode::Mmio(base) { }
|
||||
Sqe(Byte_range_ptr const &range) : Mmio<SIZE>(range) { }
|
||||
|
||||
bool valid() const { return base() != 0ul; }
|
||||
bool valid() const { return Base::base() != 0ul; }
|
||||
};
|
||||
|
||||
|
||||
struct Nvme::Sqe_header : Nvme::Sqe<0x28> { using Sqe::Sqe; };
|
||||
|
||||
|
||||
/*
|
||||
* Identify command
|
||||
*/
|
||||
struct Nvme::Sqe_identify : Nvme::Sqe
|
||||
struct Nvme::Sqe_identify : Nvme::Sqe<0x2c>
|
||||
{
|
||||
struct Cdw10 : Register<0x28, 32>
|
||||
{
|
||||
struct Cns : Bitfield< 0, 8> { }; /* controller or namespace structure */
|
||||
};
|
||||
|
||||
Sqe_identify(addr_t const base) : Sqe(base) { }
|
||||
Sqe_identify(Byte_range_ptr const &range) : Sqe(range) { }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Get feature command
|
||||
*/
|
||||
struct Nvme::Sqe_get_feature : Nvme::Sqe
|
||||
struct Nvme::Sqe_get_feature : Nvme::Sqe<0x2c>
|
||||
{
|
||||
struct Cdw10 : Register<0x28, 32>
|
||||
{
|
||||
@ -371,33 +375,37 @@ struct Nvme::Sqe_get_feature : Nvme::Sqe
|
||||
struct Sel : Bitfield< 8, 2> { }; /* select which value is returned */
|
||||
};
|
||||
|
||||
Sqe_get_feature(addr_t const base) : Sqe(base) { }
|
||||
Sqe_get_feature(Byte_range_ptr const &range) : Sqe(range) { }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Set feature command
|
||||
*/
|
||||
struct Nvme::Sqe_set_feature : Nvme::Sqe
|
||||
template <size_t SIZE>
|
||||
struct Nvme::Sqe_set_feature : Nvme::Sqe<SIZE>
|
||||
{
|
||||
struct Cdw10 : Register<0x28, 32>
|
||||
using Base = Genode::Mmio<SIZE>;
|
||||
|
||||
using Cdw10_base = Base::template Register<0x28, 32>;
|
||||
struct Cdw10 : Cdw10_base
|
||||
{
|
||||
struct Fid : Bitfield< 0, 8> { }; /* feature identifier */
|
||||
struct Sv : Bitfield<31, 1> { }; /* save */
|
||||
struct Fid : Cdw10_base::template Bitfield< 0, 8> { }; /* feature identifier */
|
||||
struct Sv : Cdw10_base::template Bitfield<31, 1> { }; /* save */
|
||||
};
|
||||
|
||||
Sqe_set_feature(addr_t const base) : Sqe(base) { }
|
||||
Sqe_set_feature(Byte_range_ptr const &range) : Sqe<SIZE>(range) { }
|
||||
};
|
||||
|
||||
|
||||
struct Hmb_de : Genode::Mmio
|
||||
struct Hmb_de : Genode::Mmio<0x10>
|
||||
{
|
||||
enum { SIZE = 16u };
|
||||
|
||||
struct Badd : Register<0x00, 64> { };
|
||||
struct Bsize : Register<0x08, 64> { };
|
||||
|
||||
Hmb_de(addr_t const base, addr_t const buffer, size_t units) : Genode::Mmio(base)
|
||||
Hmb_de(Byte_range_ptr const &range, addr_t const buffer, size_t units) : Mmio(range)
|
||||
{
|
||||
write<Badd>(buffer);
|
||||
write<Bsize>(units);
|
||||
@ -405,7 +413,7 @@ struct Hmb_de : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Nvme::Set_hmb : Nvme::Sqe_set_feature
|
||||
struct Nvme::Set_hmb : Nvme::Sqe_set_feature<0x40>
|
||||
{
|
||||
struct Cdw11 : Register<0x2c, 32>
|
||||
{
|
||||
@ -434,10 +442,10 @@ struct Nvme::Set_hmb : Nvme::Sqe_set_feature
|
||||
struct Hmdlec : Bitfield<0, 32> { }; /* host memory descriptor list entry count */
|
||||
};
|
||||
|
||||
Set_hmb(addr_t const base, uint64_t const hmdl,
|
||||
Set_hmb(Byte_range_ptr const &range, uint64_t const hmdl,
|
||||
uint32_t const units, uint32_t const entries)
|
||||
:
|
||||
Sqe_set_feature(base)
|
||||
Sqe_set_feature(range)
|
||||
{
|
||||
write<Sqe_set_feature::Cdw10::Fid>(Feature_fid::HMB);
|
||||
write<Cdw11::Ehm>(1);
|
||||
@ -452,7 +460,7 @@ struct Nvme::Set_hmb : Nvme::Sqe_set_feature
|
||||
/*
|
||||
* Create completion queue command
|
||||
*/
|
||||
struct Nvme::Sqe_create_cq : Nvme::Sqe
|
||||
struct Nvme::Sqe_create_cq : Nvme::Sqe<0x30>
|
||||
{
|
||||
struct Cdw10 : Register<0x28, 32>
|
||||
{
|
||||
@ -467,14 +475,14 @@ struct Nvme::Sqe_create_cq : Nvme::Sqe
|
||||
struct Iv : Bitfield<16, 16> { }; /* interrupt vector */
|
||||
};
|
||||
|
||||
Sqe_create_cq(addr_t const base) : Sqe(base) { }
|
||||
Sqe_create_cq(Byte_range_ptr const &range) : Sqe(range) { }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Create submission queue command
|
||||
*/
|
||||
struct Nvme::Sqe_create_sq : Nvme::Sqe
|
||||
struct Nvme::Sqe_create_sq : Nvme::Sqe<0x30>
|
||||
{
|
||||
struct Cdw10 : Register<0x28, 32>
|
||||
{
|
||||
@ -489,14 +497,14 @@ struct Nvme::Sqe_create_sq : Nvme::Sqe
|
||||
struct Cqid : Bitfield<16, 16> { }; /* completion queue identifier */
|
||||
};
|
||||
|
||||
Sqe_create_sq(addr_t const base) : Sqe(base) { }
|
||||
Sqe_create_sq(Byte_range_ptr const &range) : Sqe(range) { }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* I/O command
|
||||
*/
|
||||
struct Nvme::Sqe_io : Nvme::Sqe
|
||||
struct Nvme::Sqe_io : Nvme::Sqe<0x34>
|
||||
{
|
||||
struct Slba_lower : Register<0x28, 32> { };
|
||||
struct Slba_upper : Register<0x2c, 32> { };
|
||||
@ -507,7 +515,7 @@ struct Nvme::Sqe_io : Nvme::Sqe
|
||||
struct Nlb : Bitfield< 0, 16> { };
|
||||
};
|
||||
|
||||
Sqe_io(addr_t const base) : Sqe(base) { }
|
||||
Sqe_io(Byte_range_ptr const &range) : Sqe(range) { }
|
||||
};
|
||||
|
||||
|
||||
@ -538,12 +546,12 @@ struct Nvme::Sq : Nvme::Queue
|
||||
|
||||
using Queue::Queue;
|
||||
|
||||
addr_t next()
|
||||
Byte_range_ptr next()
|
||||
{
|
||||
addr_t a = (addr_t)local_addr<void>() + (tail * SQE_LEN);
|
||||
Genode::memset((void*)a, 0, SQE_LEN);
|
||||
char *a = local_addr<char>() + (tail * SQE_LEN);
|
||||
Genode::memset(a, 0, SQE_LEN);
|
||||
tail = (tail + 1) % max_entries;
|
||||
return a;
|
||||
return {a, size()};
|
||||
}
|
||||
};
|
||||
|
||||
@ -558,7 +566,11 @@ struct Nvme::Cq : Nvme::Queue
|
||||
|
||||
using Queue::Queue;
|
||||
|
||||
addr_t next() { return (addr_t)local_addr<void>() + (head * CQE_LEN); }
|
||||
Byte_range_ptr next()
|
||||
{
|
||||
off_t offset = head * CQE_LEN;
|
||||
return {local_addr<char>() + offset, size() - offset};
|
||||
}
|
||||
|
||||
void advance_head()
|
||||
{
|
||||
@ -574,10 +586,10 @@ struct Nvme::Cq : Nvme::Queue
|
||||
* Controller
|
||||
*/
|
||||
class Nvme::Controller : Platform::Device,
|
||||
Platform::Device::Mmio,
|
||||
Platform::Device::Mmio<0x1010>,
|
||||
Platform::Device::Irq
|
||||
{
|
||||
using Mmio = Genode::Mmio;
|
||||
using Mmio = Genode::Mmio<SIZE>;
|
||||
|
||||
public:
|
||||
|
||||
@ -974,15 +986,15 @@ class Nvme::Controller : Platform::Device,
|
||||
* \return returns address of the next free entry or 0 if there is
|
||||
* no free entry
|
||||
*/
|
||||
addr_t _admin_command(Opcode opc, uint32_t nsid, uint32_t cid)
|
||||
Byte_range_ptr _admin_command(Opcode opc, uint32_t nsid, uint32_t cid)
|
||||
{
|
||||
if (_queue_full(*_admin_sq, *_admin_cq)) { return 0ul; }
|
||||
if (_queue_full(*_admin_sq, *_admin_cq)) { return {nullptr, 0ul}; }
|
||||
|
||||
Sqe b(_admin_sq->next());
|
||||
b.write<Nvme::Sqe::Cdw0::Opc>(opc);
|
||||
b.write<Nvme::Sqe::Cdw0::Cid>(cid);
|
||||
b.write<Nvme::Sqe::Nsid>(nsid);
|
||||
return b.base();
|
||||
Sqe_header b(_admin_sq->next());
|
||||
b.write<Nvme::Sqe_header::Cdw0::Opc>(opc);
|
||||
b.write<Nvme::Sqe_header::Cdw0::Cid>(cid);
|
||||
b.write<Nvme::Sqe_header::Nsid>(nsid);
|
||||
return b.range();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1068,7 +1080,7 @@ class Nvme::Controller : Platform::Device,
|
||||
|
||||
Sqe_identify b(_admin_command(Opcode::IDENTIFY, 0, NSLIST_CID));
|
||||
|
||||
b.write<Nvme::Sqe::Prp1>(_nvme_nslist.dma_addr());
|
||||
b.write<Nvme::Sqe_identify::Prp1>(_nvme_nslist.dma_addr());
|
||||
b.write<Nvme::Sqe_identify::Cdw10::Cns>(Cns::NSLIST);
|
||||
|
||||
write<Admin_sdb::Sqt>(_admin_sq->tail);
|
||||
@ -1106,7 +1118,7 @@ class Nvme::Controller : Platform::Device,
|
||||
_nvme_query_ns[id].construct(_platform, IDENTIFY_LEN);
|
||||
|
||||
Sqe_identify b(_admin_command(Opcode::IDENTIFY, ns[id], QUERYNS_CID));
|
||||
b.write<Nvme::Sqe::Prp1>(_nvme_query_ns[id]->dma_addr());
|
||||
b.write<Nvme::Sqe_identify::Prp1>(_nvme_query_ns[id]->dma_addr());
|
||||
b.write<Nvme::Sqe_identify::Cdw10::Cns>(Cns::IDENTIFY_NS);
|
||||
|
||||
write<Admin_sdb::Sqt>(_admin_sq->tail);
|
||||
@ -1116,7 +1128,7 @@ class Nvme::Controller : Platform::Device,
|
||||
throw Initialization_failed();
|
||||
}
|
||||
|
||||
Identify_ns_data nsdata((addr_t)_nvme_query_ns[id]->local_addr<void>());
|
||||
Identify_ns_data nsdata({_nvme_query_ns[id]->local_addr<char>(), _nvme_query_ns[id]->size()});
|
||||
uint32_t const flbas = nsdata.read<Nvme::Identify_ns_data::Flbas::Formats>();
|
||||
|
||||
/* use array subscription, omit first entry */
|
||||
@ -1133,7 +1145,7 @@ class Nvme::Controller : Platform::Device,
|
||||
void _identify()
|
||||
{
|
||||
Sqe_identify b(_admin_command(Opcode::IDENTIFY, 0, IDENTIFY_CID));
|
||||
b.write<Nvme::Sqe::Prp1>(_nvme_identify.dma_addr());
|
||||
b.write<Nvme::Sqe_identify::Prp1>(_nvme_identify.dma_addr());
|
||||
b.write<Nvme::Sqe_identify::Cdw10::Cns>(Cns::IDENTIFY);
|
||||
|
||||
write<Admin_sdb::Sqt>(_admin_sq->tail);
|
||||
@ -1143,7 +1155,8 @@ class Nvme::Controller : Platform::Device,
|
||||
throw Initialization_failed();
|
||||
}
|
||||
|
||||
_identify_data.construct((addr_t)_nvme_identify.local_addr<void>());
|
||||
_identify_data.construct(
|
||||
Byte_range_ptr(_nvme_identify.local_addr<char>(), _nvme_identify.size()));
|
||||
|
||||
/* store information */
|
||||
_info.version = Genode::String<8>(read<Vs::Mjr>(), ".",
|
||||
@ -1230,17 +1243,18 @@ class Nvme::Controller : Platform::Device,
|
||||
|
||||
_hmb_chunk_registry.construct(_hmb_alloc);
|
||||
|
||||
addr_t list_base =
|
||||
(addr_t)_hmb_descr_list_buffer->local_addr<addr_t>();
|
||||
Reconstructible<Byte_range_ptr> list
|
||||
{_hmb_descr_list_buffer->local_addr<char>(), _hmb_descr_list_buffer->size()};
|
||||
|
||||
for (uint32_t i = 0; i < num_entries; i++) {
|
||||
try {
|
||||
Hmb_chunk *c =
|
||||
new (_hmb_alloc) Hmb_chunk(*_hmb_chunk_registry,
|
||||
_platform, HMB_CHUNK_SIZE);
|
||||
|
||||
Hmb_de e(list_base, c->dma_buffer.dma_addr(), HMB_CHUNK_UNITS);
|
||||
Hmb_de e(*list, c->dma_buffer.dma_addr(), HMB_CHUNK_UNITS);
|
||||
list.construct(list->start + Hmb_de::SIZE, list->num_bytes - Hmb_de::SIZE);
|
||||
|
||||
list_base += Hmb_de::SIZE;
|
||||
} catch (... /* intentional catch-all */) {
|
||||
warning("could not allocate HMB chunk");
|
||||
|
||||
@ -1284,7 +1298,7 @@ class Nvme::Controller : Platform::Device,
|
||||
Nvme::Cq &cq = *_cq[id];
|
||||
|
||||
Sqe_create_cq b(_admin_command(Opcode::CREATE_IO_CQ, 0, CREATE_IO_CQ_CID));
|
||||
b.write<Nvme::Sqe::Prp1>(cq.dma_addr());
|
||||
b.write<Nvme::Sqe_create_cq::Prp1>(cq.dma_addr());
|
||||
b.write<Nvme::Sqe_create_cq::Cdw10::Qid>(id);
|
||||
b.write<Nvme::Sqe_create_cq::Cdw10::Qsize>(_max_io_entries_mask);
|
||||
b.write<Nvme::Sqe_create_cq::Cdw11::Pc>(1);
|
||||
@ -1314,7 +1328,7 @@ class Nvme::Controller : Platform::Device,
|
||||
Nvme::Sq &sq = *_sq[id];
|
||||
|
||||
Sqe_create_sq b(_admin_command(Opcode::CREATE_IO_SQ, 0, CREATE_IO_SQ_CID));
|
||||
b.write<Nvme::Sqe::Prp1>(sq.dma_addr());
|
||||
b.write<Nvme::Sqe_create_sq::Prp1>(sq.dma_addr());
|
||||
b.write<Nvme::Sqe_create_sq::Cdw10::Qid>(id);
|
||||
b.write<Nvme::Sqe_create_sq::Cdw10::Qsize>(_max_io_entries_mask);
|
||||
b.write<Nvme::Sqe_create_sq::Cdw11::Pc>(1);
|
||||
@ -1340,7 +1354,7 @@ class Nvme::Controller : Platform::Device,
|
||||
Signal_context_capability irq_sigh)
|
||||
:
|
||||
Platform::Device(platform),
|
||||
Platform::Device::Mmio((Platform::Device&)*this),
|
||||
Platform::Device::Mmio<SIZE>((Platform::Device&)*this),
|
||||
Platform::Device::Irq((Platform::Device&)*this),
|
||||
_env(env), _platform(platform), _delayer(delayer)
|
||||
{
|
||||
@ -1419,14 +1433,14 @@ class Nvme::Controller : Platform::Device,
|
||||
*
|
||||
* \return returns virtual address of the I/O command
|
||||
*/
|
||||
addr_t io_command(uint16_t nsid, uint16_t cid)
|
||||
Byte_range_ptr io_command(uint16_t nsid, uint16_t cid)
|
||||
{
|
||||
Nvme::Sq &sq = *_sq[nsid];
|
||||
|
||||
Sqe e(sq.next());
|
||||
e.write<Nvme::Sqe::Cdw0::Cid>(cid);
|
||||
e.write<Nvme::Sqe::Nsid>(nsid);
|
||||
return e.base();
|
||||
Sqe_header e(sq.next());
|
||||
e.write<Nvme::Sqe_header::Cdw0::Cid>(cid);
|
||||
e.write<Nvme::Sqe_header::Nsid>(nsid);
|
||||
return e.range();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1755,7 +1769,7 @@ class Nvme::Driver : Genode::Noncopyable
|
||||
** MMIO Controller **
|
||||
*********************/
|
||||
|
||||
struct Timer_delayer : Genode::Mmio::Delayer,
|
||||
struct Timer_delayer : Genode::Mmio<0>::Delayer,
|
||||
Timer::Connection
|
||||
{
|
||||
Timer_delayer(Genode::Env &env)
|
||||
@ -1985,12 +1999,12 @@ class Nvme::Driver : Genode::Noncopyable
|
||||
|
||||
Nvme::Sqe_io b(_nvme_ctrlr.io_command(Nvme::IO_NSID, cid));
|
||||
Nvme::Opcode const op = write ? Nvme::Opcode::WRITE : Nvme::Opcode::READ;
|
||||
b.write<Nvme::Sqe::Cdw0::Opc>(op);
|
||||
b.write<Nvme::Sqe::Prp1>(request_pa);
|
||||
b.write<Nvme::Sqe_io::Cdw0::Opc>(op);
|
||||
b.write<Nvme::Sqe_io::Prp1>(request_pa);
|
||||
|
||||
/* payload will fit into 2 mps chunks */
|
||||
if (len > Nvme::MPS && !need_list) {
|
||||
b.write<Nvme::Sqe::Prp2>(request_pa + Nvme::MPS);
|
||||
b.write<Nvme::Sqe_io::Prp2>(request_pa + Nvme::MPS);
|
||||
} else if (need_list) {
|
||||
|
||||
/* get page to store list of mps chunks */
|
||||
@ -2018,7 +2032,7 @@ class Nvme::Driver : Genode::Noncopyable
|
||||
pe[i] = npa;
|
||||
npa += Nvme::MPS;
|
||||
}
|
||||
b.write<Nvme::Sqe::Prp2>(pa);
|
||||
b.write<Nvme::Sqe_io::Prp2>(pa);
|
||||
}
|
||||
|
||||
b.write<Nvme::Sqe_io::Slba_lower>(uint32_t(lba));
|
||||
@ -2035,7 +2049,7 @@ class Nvme::Driver : Genode::Noncopyable
|
||||
.id = id };
|
||||
|
||||
Nvme::Sqe_io b(_nvme_ctrlr.io_command(Nvme::IO_NSID, cid));
|
||||
b.write<Nvme::Sqe::Cdw0::Opc>(Nvme::Opcode::FLUSH);
|
||||
b.write<Nvme::Sqe_io::Cdw0::Opc>(Nvme::Opcode::FLUSH);
|
||||
}
|
||||
|
||||
void _submit_trim(Block::Request const request)
|
||||
@ -2050,7 +2064,7 @@ class Nvme::Driver : Genode::Noncopyable
|
||||
Block::sector_t const lba = request.operation.block_number;
|
||||
|
||||
Nvme::Sqe_io b(_nvme_ctrlr.io_command(Nvme::IO_NSID, cid));
|
||||
b.write<Nvme::Sqe::Cdw0::Opc>(Nvme::Opcode::WRITE_ZEROS);
|
||||
b.write<Nvme::Sqe_io::Cdw0::Opc>(Nvme::Opcode::WRITE_ZEROS);
|
||||
b.write<Nvme::Sqe_io::Slba_lower>(uint32_t(lba));
|
||||
b.write<Nvme::Sqe_io::Slba_upper>(uint32_t(lba >> 32u));
|
||||
|
||||
|
@ -52,8 +52,10 @@ struct Config_helper
|
||||
Driver::Device const & _dev;
|
||||
Driver::Device::Pci_config const & _cfg;
|
||||
|
||||
Attached_io_mem_dataspace _io_mem { _env, _cfg.addr, 0x1000 };
|
||||
Config _config { (addr_t)_io_mem.local_addr<void>() };
|
||||
static constexpr size_t IO_MEM_SIZE = 0x1000;
|
||||
|
||||
Attached_io_mem_dataspace _io_mem { _env, _cfg.addr, IO_MEM_SIZE };
|
||||
Config _config { {_io_mem.local_addr<char>(), IO_MEM_SIZE} };
|
||||
|
||||
Config_helper(Env & env,
|
||||
Driver::Device const & dev,
|
||||
@ -125,8 +127,8 @@ struct Config_helper
|
||||
_config.write<Config::Command>(cmd);
|
||||
|
||||
/* apply different PCI quirks, bios handover etc. */
|
||||
Driver::pci_uhci_quirks(_env, _dev, _cfg, _config.base());
|
||||
Driver::pci_ehci_quirks(_env, _dev, _cfg, _config.base());
|
||||
Driver::pci_uhci_quirks(_env, _dev, _cfg, _config.range());
|
||||
Driver::pci_ehci_quirks(_env, _dev, _cfg, _config.range());
|
||||
Driver::pci_hd_audio_quirks(_cfg, _config);
|
||||
|
||||
_config.write<Config::Command>(cmd_old);
|
||||
@ -163,8 +165,10 @@ void Driver::pci_msi_enable(Env & env,
|
||||
Irq_session::Info const info,
|
||||
Irq_session::Type type)
|
||||
{
|
||||
Attached_io_mem_dataspace io_mem { env, cfg_space, 0x1000 };
|
||||
Config config { (addr_t)io_mem.local_addr<void>() };
|
||||
static constexpr size_t IO_MEM_SIZE = 0x1000;
|
||||
|
||||
Attached_io_mem_dataspace io_mem { env, cfg_space, IO_MEM_SIZE };
|
||||
Config config { {io_mem.local_addr<char>(), IO_MEM_SIZE} };
|
||||
config.scan();
|
||||
|
||||
if (type == Irq_session::TYPE_MSIX && config.msi_x_cap.constructed()) {
|
||||
@ -174,14 +178,15 @@ void Driver::pci_msi_enable(Env & env,
|
||||
unsigned idx = dc.io_mem_index({config.msi_x_cap->bar()});
|
||||
Io_mem_session_client dsc(dc.io_mem(idx, range));
|
||||
Attached_dataspace msix_table_ds(env.rm(), dsc.dataspace());
|
||||
addr_t msix_table_start = (addr_t)msix_table_ds.local_addr<void>()
|
||||
+ config.msi_x_cap->table_offset();
|
||||
Byte_range_ptr msix_table = {
|
||||
msix_table_ds.local_addr<char>() + config.msi_x_cap->table_offset(),
|
||||
msix_table_ds.size() - config.msi_x_cap->table_offset() };
|
||||
|
||||
/* disable all msi-x table entries beside the first one */
|
||||
unsigned slots = config.msi_x_cap->slots();
|
||||
for (unsigned i = 0; i < slots; i++) {
|
||||
using Entry = Config::Msi_x_capability::Table_entry;
|
||||
Entry e (msix_table_start + Entry::SIZE * i);
|
||||
Entry e ({msix_table.start + Entry::SIZE*i, msix_table.num_bytes - Entry::SIZE*i});
|
||||
if (!i) {
|
||||
uint32_t lower = info.address & 0xfffffffc;
|
||||
uint32_t upper = sizeof(info.address) > 4 ?
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
namespace Driver {
|
||||
static void pci_ehci_quirks(Env &, Device const &,
|
||||
Device::Pci_config const &, addr_t);
|
||||
Device::Pci_config const &, Pci::Config const &);
|
||||
}
|
||||
|
||||
|
||||
void Driver::pci_ehci_quirks(Env & env,
|
||||
Device const & dev,
|
||||
Device::Pci_config const & cfg,
|
||||
addr_t base)
|
||||
Pci::Config const & pci_config)
|
||||
{
|
||||
enum { EHCI_CLASS_CODE = 0xc0320 };
|
||||
|
||||
@ -31,7 +31,7 @@ void Driver::pci_ehci_quirks(Env & env,
|
||||
return;
|
||||
|
||||
/* EHCI host controller register definitions */
|
||||
struct Ehci : Mmio
|
||||
struct Ehci : Mmio<0x44>
|
||||
{
|
||||
struct Capability_parameters : Register<0x8, 32>
|
||||
{
|
||||
@ -42,7 +42,7 @@ void Driver::pci_ehci_quirks(Env & env,
|
||||
using Mmio::Mmio;
|
||||
};
|
||||
|
||||
struct Ehci_pci : Mmio
|
||||
struct Ehci_pci : Mmio<0x64>
|
||||
{
|
||||
struct Port_wake : Register<0x62, 16> {};
|
||||
|
||||
@ -50,7 +50,7 @@ void Driver::pci_ehci_quirks(Env & env,
|
||||
};
|
||||
|
||||
/* PCI extended capability for EHCI */
|
||||
struct Cap : Mmio
|
||||
struct Cap : Mmio<0x8>
|
||||
{
|
||||
struct Pointer : Register<0x0, 16>
|
||||
{
|
||||
@ -72,16 +72,18 @@ void Driver::pci_ehci_quirks(Env & env,
|
||||
if (!bar.valid() || bar.number != 0)
|
||||
return;
|
||||
|
||||
Ehci_pci pw(base);
|
||||
Ehci_pci pw(pci_config.range());
|
||||
|
||||
Attached_io_mem_dataspace iomem(env, range.start, 0x1000);
|
||||
Ehci ehci((addr_t)iomem.local_addr<void>());
|
||||
static constexpr size_t IO_MEM_SIZE = 0x1000;
|
||||
|
||||
Attached_io_mem_dataspace iomem(env, range.start, IO_MEM_SIZE);
|
||||
Ehci ehci({iomem.local_addr<char>(), IO_MEM_SIZE});
|
||||
addr_t offset =
|
||||
ehci.read<Ehci::Capability_parameters::Extended_cap_pointer>();
|
||||
|
||||
/* iterate over EHCI extended capabilities */
|
||||
while (offset) {
|
||||
Cap cap(base + offset);
|
||||
Cap cap(pci_config.range_at(offset));
|
||||
if (cap.read<Cap::Pointer::Id>() != Cap::Pointer::Id::SYNC)
|
||||
break;
|
||||
|
||||
|
@ -27,7 +27,7 @@ void Driver::pci_hd_audio_quirks(Device::Pci_config const & cfg, Pci::Config & c
|
||||
return;
|
||||
|
||||
/* PCI configuration register for HDAUDIO */
|
||||
struct Hdaudio : Mmio
|
||||
struct Hdaudio : Mmio<0x7a>
|
||||
{
|
||||
struct Traffic_class_select : Register<0x44, 8> {};
|
||||
|
||||
@ -46,7 +46,7 @@ void Driver::pci_hd_audio_quirks(Device::Pci_config const & cfg, Pci::Config & c
|
||||
|
||||
config.write<Pci::Config::Command::Fast_back_to_back_enable>(1);
|
||||
|
||||
Hdaudio audio(config.base());
|
||||
Hdaudio audio(config.range());
|
||||
audio.write<Hdaudio::Traffic_class_select>(0);
|
||||
|
||||
if (cfg.vendor_id == 0x8086)
|
||||
|
@ -91,7 +91,7 @@ void Driver::pci_intel_graphics_info(Device::Pci_config const & cfg,
|
||||
return;
|
||||
|
||||
/* PCI configuration registers of host bridge */
|
||||
struct Host_bridge : Mmio
|
||||
struct Host_bridge : Mmio<0x54>
|
||||
{
|
||||
struct Gen_old_gmch_control : Register<0x52, 16> {};
|
||||
struct Gen_gmch_control : Register<0x50, 16> {};
|
||||
@ -105,8 +105,10 @@ void Driver::pci_intel_graphics_info(Device::Pci_config const & cfg,
|
||||
if (cfg.bus_num || cfg.dev_num || cfg.func_num)
|
||||
return;
|
||||
|
||||
Attached_io_mem_dataspace io_mem(env, cfg.addr, 0x1000);
|
||||
Host_bridge config((addr_t)io_mem.local_addr<void>());
|
||||
static constexpr size_t IO_MEM_SIZE = 0x1000;
|
||||
|
||||
Attached_io_mem_dataspace io_mem(env, cfg.addr, IO_MEM_SIZE);
|
||||
Host_bridge config({io_mem.local_addr<char>(), IO_MEM_SIZE});
|
||||
unsigned gen = pci_intel_graphics_generation(cfg.device_id);
|
||||
uint16_t gmch = 0;
|
||||
|
||||
|
@ -17,14 +17,14 @@
|
||||
|
||||
namespace Driver {
|
||||
static void pci_uhci_quirks(Env &, Device const &,
|
||||
Device::Pci_config const &, addr_t);
|
||||
Device::Pci_config const &, Pci::Config const &);
|
||||
}
|
||||
|
||||
|
||||
void Driver::pci_uhci_quirks(Env & env,
|
||||
Device const & dev,
|
||||
Device::Pci_config const & cfg,
|
||||
addr_t base)
|
||||
Pci::Config const & pci_config)
|
||||
{
|
||||
enum { UHCI_CLASS_CODE = 0xc0300 };
|
||||
|
||||
@ -32,7 +32,7 @@ void Driver::pci_uhci_quirks(Env & env,
|
||||
return;
|
||||
|
||||
/* PCI configuration register for UHCI */
|
||||
struct Uhci : Mmio
|
||||
struct Uhci : Mmio<0xc6>
|
||||
{
|
||||
struct Usb_legacy_support : Register<0xc0, 16>
|
||||
{
|
||||
@ -56,7 +56,7 @@ void Driver::pci_uhci_quirks(Env & env,
|
||||
if (!range.size) range = r; });
|
||||
|
||||
Io_port_connection io_ports(env, range.addr, range.size);
|
||||
Uhci config(base);
|
||||
Uhci config(pci_config.range());
|
||||
|
||||
bool have_to_reset = false;
|
||||
uint16_t UHCI_CMD = range.addr;
|
||||
|
@ -33,7 +33,7 @@ void Driver::pci_virtio_info(Device const & dev,
|
||||
|
||||
struct Virtio : Pci::Config
|
||||
{
|
||||
struct Capability : Pci::Config::Pci_capability
|
||||
struct Capability : Pci::Config::Pci_capability<0x14>
|
||||
{
|
||||
enum { COMMON = 1, NOTIFY = 2, ISR = 3, DEVICE = 4 };
|
||||
|
||||
@ -43,7 +43,7 @@ void Driver::pci_virtio_info(Device const & dev,
|
||||
struct Length : Register<0xc, 32> {};
|
||||
struct Offset_factor : Register<0x10, 32> {};
|
||||
|
||||
using Pci::Config::Pci_capability::Pci_capability;
|
||||
using Pci_capability::Pci_capability;
|
||||
|
||||
bool valid()
|
||||
{
|
||||
@ -100,18 +100,20 @@ void Driver::pci_virtio_info(Device const & dev,
|
||||
|
||||
uint16_t off = read<Capability_pointer>();
|
||||
while (off) {
|
||||
Capability cap(base() + off);
|
||||
if (cap.read<Pci_capability::Id>() ==
|
||||
Pci_capability::Id::VENDOR &&
|
||||
Capability cap(Mmio::range_at(off));
|
||||
if (cap.read<Capability::Id>() ==
|
||||
Capability::Id::VENDOR &&
|
||||
cap.valid())
|
||||
capability(cap, dev, xml);
|
||||
off = cap.read<Pci_capability::Pointer>();
|
||||
off = cap.read<Capability::Pointer>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Attached_io_mem_dataspace io_mem(env, cfg.addr, 0x1000);
|
||||
Virtio config((addr_t)io_mem.local_addr<void>());
|
||||
static constexpr size_t IO_MEM_SIZE = 0x1000;
|
||||
|
||||
Attached_io_mem_dataspace io_mem(env, cfg.addr, IO_MEM_SIZE);
|
||||
Virtio config({io_mem.local_addr<char>(), IO_MEM_SIZE});
|
||||
config.for_each_capability(dev, xml);
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,8 @@ struct Ps2::Main
|
||||
|
||||
Device _device { _platform };
|
||||
|
||||
Device::Mmio _mmio_keyboard { _device, { 0 } };
|
||||
Device::Mmio _mmio_mouse { _device, { 1 } };
|
||||
Device::Mmio<0> _mmio_keyboard { _device, { 0 } };
|
||||
Device::Mmio<0> _mmio_mouse { _device, { 1 } };
|
||||
|
||||
Device::Irq _irq_keyboard { _device, { 0 } };
|
||||
Device::Irq _irq_mouse { _device, { 1 } };
|
||||
|
@ -77,7 +77,7 @@ class Pl050
|
||||
|
||||
public:
|
||||
|
||||
_Channel(Platform::Device::Mmio &mmio)
|
||||
_Channel(Platform::Device::Mmio<0> &mmio)
|
||||
:
|
||||
_reg_base(mmio.local_addr<Genode::uint32_t>())
|
||||
{ }
|
||||
@ -119,8 +119,8 @@ class Pl050
|
||||
|
||||
public:
|
||||
|
||||
Pl050(Platform::Device::Mmio &keyboard_mmio,
|
||||
Platform::Device::Mmio &mouse_mmio)
|
||||
Pl050(Platform::Device::Mmio<0> &keyboard_mmio,
|
||||
Platform::Device::Mmio<0> &mouse_mmio)
|
||||
:
|
||||
_kbd(keyboard_mmio), _aux(mouse_mmio)
|
||||
{
|
||||
|
@ -524,7 +524,7 @@ Driver::Driver(Env & env, Platform::Connection & platform)
|
||||
:
|
||||
Driver_base(env.ram()),
|
||||
Platform::Device(platform),
|
||||
Platform::Device::Mmio(*static_cast<Platform::Device *>(this)),
|
||||
Platform::Device::Mmio<SIZE>(*static_cast<Platform::Device *>(this)),
|
||||
_env(env),
|
||||
_platform(platform)
|
||||
{
|
||||
|
@ -27,9 +27,9 @@ namespace Sd_card { class Driver; }
|
||||
|
||||
class Sd_card::Driver : public Driver_base,
|
||||
private Platform::Device,
|
||||
private Platform::Device::Mmio
|
||||
private Platform::Device::Mmio<0x100>
|
||||
{
|
||||
using Mmio = Genode::Mmio;
|
||||
using Mmio = Genode::Mmio<SIZE>;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -142,7 +142,7 @@ Driver::Driver(Env &env, Platform::Connection & platform)
|
||||
:
|
||||
Block::Driver(env.ram()),
|
||||
Platform::Device(platform),
|
||||
Platform::Device::Mmio(*this, { 0 }),
|
||||
Platform::Device::Mmio<SIZE>(*this, { 0 }),
|
||||
_platform(platform),
|
||||
_timer(env)
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ namespace Sd_card {
|
||||
|
||||
class Sd_card::Driver : public Block::Driver,
|
||||
private Platform::Device,
|
||||
private Platform::Device::Mmio
|
||||
private Platform::Device::Mmio<0>
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -114,9 +114,9 @@ namespace Sd_card {
|
||||
};
|
||||
|
||||
|
||||
struct Ext_csd : Mmio
|
||||
struct Ext_csd : Mmio<0xd8>
|
||||
{
|
||||
Ext_csd(addr_t base) : Mmio(base) { }
|
||||
using Mmio::Mmio;
|
||||
|
||||
struct Revision : Register<0xc0, 8> { };
|
||||
struct Sector_count : Register<0xd4, 32> { };
|
||||
|
@ -27,7 +27,7 @@ namespace I2c
|
||||
}
|
||||
|
||||
|
||||
class I2c::I2c : Platform::Device::Mmio
|
||||
class I2c::I2c : Platform::Device::Mmio<0x12>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -112,7 +112,7 @@ class I2c::I2c : Platform::Device::Mmio
|
||||
public:
|
||||
|
||||
I2c(Genode::Env & env, Platform::Device & dev)
|
||||
: Platform::Device::Mmio(dev, {0}),
|
||||
: Platform::Device::Mmio<SIZE>(dev, {0}),
|
||||
_irq_handler(env, dev)
|
||||
{
|
||||
write<Control>(0);
|
||||
|
@ -34,7 +34,7 @@ using Genode::addr_t;
|
||||
** USB Command Block/Status Wrapper implementation **
|
||||
*****************************************************/
|
||||
|
||||
struct Usb::Cbw : Genode::Mmio
|
||||
struct Usb::Cbw : Genode::Mmio<0xf>
|
||||
{
|
||||
enum { LENGTH = 31 };
|
||||
|
||||
@ -46,8 +46,8 @@ struct Usb::Cbw : Genode::Mmio
|
||||
struct Lun : Register<0xd, 8> { }; /* logical unit number */
|
||||
struct Cbl : Register<0xe, 8> { }; /* command buffer length */
|
||||
|
||||
Cbw(addr_t addr, uint32_t t, uint32_t d,
|
||||
uint8_t f, uint8_t l, uint8_t len) : Mmio(addr)
|
||||
Cbw(Byte_range_ptr const &range, uint32_t t, uint32_t d,
|
||||
uint8_t f, uint8_t l, uint8_t len) : Mmio(range)
|
||||
{
|
||||
write<Sig>(SIG);
|
||||
write<Tag>(t);
|
||||
@ -72,11 +72,11 @@ struct Usb::Cbw : Genode::Mmio
|
||||
struct Test_unit_ready : Usb::Cbw,
|
||||
Scsi::Test_unit_ready
|
||||
{
|
||||
Test_unit_ready(addr_t addr, uint32_t tag, uint8_t lun)
|
||||
Test_unit_ready(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun)
|
||||
:
|
||||
Cbw(addr, tag, 0, Usb::ENDPOINT_IN, lun,
|
||||
Cbw(range, tag, 0, Usb::ENDPOINT_IN, lun,
|
||||
Scsi::Test_unit_ready::LENGTH),
|
||||
Scsi::Test_unit_ready(addr+15)
|
||||
Scsi::Test_unit_ready(Cbw::range_at(15))
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -90,11 +90,11 @@ struct Test_unit_ready : Usb::Cbw,
|
||||
|
||||
struct Request_sense : Usb::Cbw, Scsi::Request_sense
|
||||
{
|
||||
Request_sense(addr_t addr, uint32_t tag, uint8_t lun)
|
||||
Request_sense(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun)
|
||||
:
|
||||
Cbw(addr, tag, Scsi::Request_sense_response::LENGTH,
|
||||
Cbw(range, tag, Scsi::Request_sense_response::LENGTH,
|
||||
Usb::ENDPOINT_IN, lun, Scsi::Request_sense::LENGTH),
|
||||
Scsi::Request_sense(addr+15)
|
||||
Scsi::Request_sense(Cbw::range_at(15))
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -108,10 +108,10 @@ struct Request_sense : Usb::Cbw, Scsi::Request_sense
|
||||
|
||||
struct Start_stop : Usb::Cbw, Scsi::Start_stop
|
||||
{
|
||||
Start_stop(addr_t addr, uint32_t tag, uint8_t lun)
|
||||
Start_stop(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun)
|
||||
:
|
||||
Cbw(addr, tag, 0, Usb::ENDPOINT_IN, lun, Scsi::Start_stop::LENGTH),
|
||||
Scsi::Start_stop(addr+15)
|
||||
Cbw(range, tag, 0, Usb::ENDPOINT_IN, lun, Scsi::Start_stop::LENGTH),
|
||||
Scsi::Start_stop(Cbw::range_at(15))
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -125,11 +125,11 @@ struct Start_stop : Usb::Cbw, Scsi::Start_stop
|
||||
|
||||
struct Inquiry : Usb::Cbw, Scsi::Inquiry
|
||||
{
|
||||
Inquiry(addr_t addr, uint32_t tag, uint8_t lun)
|
||||
Inquiry(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun)
|
||||
:
|
||||
Cbw(addr, tag, Scsi::Inquiry_response::LENGTH,
|
||||
Cbw(range, tag, Scsi::Inquiry_response::LENGTH,
|
||||
Usb::ENDPOINT_IN, lun, Scsi::Inquiry::LENGTH),
|
||||
Scsi::Inquiry(addr+15)
|
||||
Scsi::Inquiry(Cbw::range_at(15))
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -143,11 +143,11 @@ struct Inquiry : Usb::Cbw, Scsi::Inquiry
|
||||
|
||||
struct Read_capacity_10 : Usb::Cbw, Scsi::Read_capacity_10
|
||||
{
|
||||
Read_capacity_10(addr_t addr, uint32_t tag, uint8_t lun)
|
||||
Read_capacity_10(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun)
|
||||
:
|
||||
Cbw(addr, tag, Scsi::Capacity_response_10::LENGTH,
|
||||
Cbw(range, tag, Scsi::Capacity_response_10::LENGTH,
|
||||
Usb::ENDPOINT_IN, lun, Scsi::Read_capacity_10::LENGTH),
|
||||
Scsi::Read_capacity_10(addr+15)
|
||||
Scsi::Read_capacity_10(Cbw::range_at(15))
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -161,12 +161,12 @@ struct Read_capacity_10 : Usb::Cbw, Scsi::Read_capacity_10
|
||||
|
||||
struct Read_10 : Usb::Cbw, Scsi::Read_10
|
||||
{
|
||||
Read_10(addr_t addr, uint32_t tag, uint8_t lun,
|
||||
Read_10(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun,
|
||||
uint32_t lba, uint16_t len, uint32_t block_size)
|
||||
:
|
||||
Cbw(addr, tag, len * block_size,
|
||||
Cbw(range, tag, len * block_size,
|
||||
Usb::ENDPOINT_IN, lun, Scsi::Read_10::LENGTH),
|
||||
Scsi::Read_10(addr+15, lba, len)
|
||||
Scsi::Read_10(Cbw::range_at(15), lba, len)
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -180,12 +180,12 @@ struct Read_10 : Usb::Cbw, Scsi::Read_10
|
||||
|
||||
struct Write_10 : Usb::Cbw, Scsi::Write_10
|
||||
{
|
||||
Write_10(addr_t addr, uint32_t tag, uint8_t lun,
|
||||
Write_10(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun,
|
||||
uint32_t lba, uint16_t len, uint32_t block_size)
|
||||
:
|
||||
Cbw(addr, tag, len * block_size,
|
||||
Cbw(range, tag, len * block_size,
|
||||
Usb::ENDPOINT_OUT, lun, Scsi::Write_10::LENGTH),
|
||||
Scsi::Write_10(addr+15, lba, len)
|
||||
Scsi::Write_10(Cbw::range_at(15), lba, len)
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -199,11 +199,11 @@ struct Write_10 : Usb::Cbw, Scsi::Write_10
|
||||
|
||||
struct Read_capacity_16 : Usb::Cbw, Scsi::Read_capacity_16
|
||||
{
|
||||
Read_capacity_16(addr_t addr, uint32_t tag, uint8_t lun)
|
||||
Read_capacity_16(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun)
|
||||
:
|
||||
Cbw(addr, tag, Scsi::Capacity_response_16::LENGTH,
|
||||
Cbw(range, tag, Scsi::Capacity_response_16::LENGTH,
|
||||
Usb::ENDPOINT_IN, lun, Scsi::Read_capacity_16::LENGTH),
|
||||
Scsi::Read_capacity_16(addr+15)
|
||||
Scsi::Read_capacity_16(Cbw::range_at(15))
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -217,12 +217,12 @@ struct Read_capacity_16 : Usb::Cbw, Scsi::Read_capacity_16
|
||||
|
||||
struct Read_16 : Usb::Cbw, Scsi::Read_16
|
||||
{
|
||||
Read_16(addr_t addr, uint32_t tag, uint8_t lun,
|
||||
Read_16(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun,
|
||||
uint64_t lba, uint32_t len, uint32_t block_size)
|
||||
:
|
||||
Cbw(addr, tag, len * block_size,
|
||||
Cbw(range, tag, len * block_size,
|
||||
Usb::ENDPOINT_IN, lun, Scsi::Read_16::LENGTH),
|
||||
Scsi::Read_16(addr+15, lba, len)
|
||||
Scsi::Read_16(Cbw::range_at(15), (uint32_t)lba, (uint16_t)len)
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -236,12 +236,12 @@ struct Read_16 : Usb::Cbw, Scsi::Read_16
|
||||
|
||||
struct Write_16 : Usb::Cbw, Scsi::Write_16
|
||||
{
|
||||
Write_16(addr_t addr, uint32_t tag, uint8_t lun,
|
||||
Write_16(Genode::Byte_range_ptr const &range, uint32_t tag, uint8_t lun,
|
||||
uint64_t lba, uint32_t len, uint32_t block_size)
|
||||
:
|
||||
Cbw(addr, tag, len * block_size,
|
||||
Cbw(range, tag, len * block_size,
|
||||
Usb::ENDPOINT_OUT, lun, Scsi::Write_16::LENGTH),
|
||||
Scsi::Write_16(addr+15, lba, len)
|
||||
Scsi::Write_16(Cbw::range_at(15), (uint32_t)lba, (uint16_t)len)
|
||||
{ if (verbose_scsi) dump(); }
|
||||
|
||||
void dump()
|
||||
@ -253,7 +253,7 @@ struct Write_16 : Usb::Cbw, Scsi::Write_16
|
||||
};
|
||||
|
||||
|
||||
struct Usb::Csw : Genode::Mmio
|
||||
struct Usb::Csw : Genode::Mmio<0xd>
|
||||
{
|
||||
enum { LENGTH = 13 };
|
||||
|
||||
@ -264,7 +264,7 @@ struct Usb::Csw : Genode::Mmio
|
||||
enum { PASSED = 0, FAILED = 1, PHASE_ERROR = 2 };
|
||||
struct Sts : Register<0xc, 8> { }; /* status */
|
||||
|
||||
Csw(addr_t addr) : Mmio(addr) { }
|
||||
Csw(Genode::Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
uint32_t sig() const { return read<Sig>(); }
|
||||
uint32_t tag() const { return read<Tag>(); }
|
||||
|
@ -238,14 +238,14 @@ struct Usb::Block_driver : Usb::Completion
|
||||
}
|
||||
|
||||
int const actual_size = p.transfer.actual_size;
|
||||
char * const data = reinterpret_cast<char*>(iface.content(p));
|
||||
Byte_range_ptr data {(char *)iface.content(p), p.size()};
|
||||
|
||||
using namespace Scsi;
|
||||
|
||||
switch (actual_size) {
|
||||
case Inquiry_response::LENGTH:
|
||||
{
|
||||
Inquiry_response r((addr_t)data);
|
||||
Inquiry_response r(data);
|
||||
if (verbose_scsi) r.dump();
|
||||
|
||||
if (!r.sbc()) {
|
||||
@ -258,7 +258,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
}
|
||||
case Capacity_response_10::LENGTH:
|
||||
{
|
||||
Capacity_response_10 r((addr_t)data);
|
||||
Capacity_response_10 r(data);
|
||||
if (verbose_scsi) r.dump();
|
||||
|
||||
block_count = r.last_block() + 1;
|
||||
@ -267,7 +267,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
}
|
||||
case Capacity_response_16::LENGTH:
|
||||
{
|
||||
Capacity_response_16 r((addr_t)data);
|
||||
Capacity_response_16 r(data);
|
||||
if (verbose_scsi) r.dump();
|
||||
|
||||
block_count = r.last_block() + 1;
|
||||
@ -276,7 +276,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
}
|
||||
case Request_sense_response::LENGTH:
|
||||
{
|
||||
Request_sense_response r((addr_t)data);
|
||||
Request_sense_response r(data);
|
||||
if (verbose_scsi) r.dump();
|
||||
|
||||
uint8_t const asc = r.read<Request_sense_response::Asc>();
|
||||
@ -322,7 +322,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
}
|
||||
case Csw::LENGTH:
|
||||
{
|
||||
Csw csw((addr_t)data);
|
||||
Csw csw(data);
|
||||
|
||||
uint32_t const sig = csw.sig();
|
||||
if (sig != Csw::SIG) {
|
||||
@ -528,6 +528,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
*/
|
||||
|
||||
char cbw_buffer[Cbw::LENGTH];
|
||||
Byte_range_ptr cbw_buf_range {(char *)cbw_buffer, Cbw::LENGTH};
|
||||
|
||||
/*
|
||||
* We should probably execute the SCSI REPORT_LUNS command first
|
||||
@ -537,7 +538,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
*/
|
||||
|
||||
/* Scsi::Opcode::INQUIRY */
|
||||
Inquiry inq((addr_t)cbw_buffer, INQ_TAG, active_lun);
|
||||
Inquiry inq(cbw_buf_range, INQ_TAG, active_lun);
|
||||
|
||||
cbw(cbw_buffer, init, true);
|
||||
resp(Scsi::Inquiry_response::LENGTH, init, true);
|
||||
@ -559,13 +560,13 @@ struct Usb::Block_driver : Usb::Completion
|
||||
enum { MAX_RETRIES = 10 };
|
||||
int retries;
|
||||
for (retries = 0; retries < MAX_RETRIES; retries++) {
|
||||
Test_unit_ready unit_ready((addr_t)cbw_buffer, RDY_TAG, active_lun);
|
||||
Test_unit_ready unit_ready(cbw_buf_range, RDY_TAG, active_lun);
|
||||
|
||||
cbw(cbw_buffer, init, true);
|
||||
csw(init, true);
|
||||
|
||||
if (!init.unit_ready) {
|
||||
Request_sense sense((addr_t)cbw_buffer, REQ_TAG, active_lun);
|
||||
Request_sense sense(cbw_buf_range, REQ_TAG, active_lun);
|
||||
|
||||
cbw(cbw_buffer, init, true);
|
||||
resp(Scsi::Request_sense_response::LENGTH, init, true);
|
||||
@ -582,7 +583,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
} else if (init.start_stop) {
|
||||
|
||||
init.start_stop = false;
|
||||
Start_stop start_stop((addr_t)cbw_buffer, SS_TAG, active_lun);
|
||||
Start_stop start_stop(cbw_buf_range, SS_TAG, active_lun);
|
||||
|
||||
cbw(cbw_buffer, init, true);
|
||||
csw(init, true);
|
||||
@ -609,7 +610,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
*/
|
||||
|
||||
/* Scsi::Opcode::READ_CAPACITY_10 */
|
||||
Read_capacity_10 read_cap((addr_t)cbw_buffer, CAP_TAG, active_lun);
|
||||
Read_capacity_10 read_cap(cbw_buf_range, CAP_TAG, active_lun);
|
||||
|
||||
cbw(cbw_buffer, init, true);
|
||||
resp(Scsi::Capacity_response_10::LENGTH, init, true);
|
||||
@ -626,7 +627,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
*/
|
||||
if (init.block_count > ~(uint32_t)0U) {
|
||||
|
||||
Read_capacity_16 read_cap((addr_t)cbw_buffer, CAP_TAG, active_lun);
|
||||
Read_capacity_16 read_cap(cbw_buf_range, CAP_TAG, active_lun);
|
||||
|
||||
init.read_capacity = false;
|
||||
|
||||
@ -779,7 +780,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
warning("This is not the actual size you are looking for");
|
||||
|
||||
do {
|
||||
Csw csw((addr_t)iface.content(p));
|
||||
Csw csw({(char *)iface.content(p), p.size()});
|
||||
|
||||
uint32_t const sig = csw.sig();
|
||||
if (sig != Csw::SIG) {
|
||||
@ -879,12 +880,13 @@ struct Usb::Block_driver : Usb::Completion
|
||||
* before entering this function
|
||||
*/
|
||||
char cb[Cbw::LENGTH];
|
||||
Byte_range_ptr cb_range {(char *)cb, Cbw::LENGTH};
|
||||
if (read) {
|
||||
if (force_cmd_16) Read_16 r((addr_t)cb, t, active_lun, lba, c, _block_size);
|
||||
else Read_10 r((addr_t)cb, t, active_lun, (uint32_t)lba, c, _block_size);
|
||||
if (force_cmd_16) Read_16 r(cb_range, t, active_lun, lba, c, _block_size);
|
||||
else Read_10 r(cb_range, t, active_lun, (uint32_t)lba, c, _block_size);
|
||||
} else {
|
||||
if (force_cmd_16) Write_16 w((addr_t)cb, t, active_lun, lba, c, _block_size);
|
||||
else Write_10 w((addr_t)cb, t, active_lun, (uint32_t)lba, c, _block_size);
|
||||
if (force_cmd_16) Write_16 w(cb_range, t, active_lun, lba, c, _block_size);
|
||||
else Write_10 w(cb_range, t, active_lun, (uint32_t)lba, c, _block_size);
|
||||
}
|
||||
|
||||
cbw(cb, *this);
|
||||
|
@ -84,7 +84,7 @@ namespace Scsi {
|
||||
* SCSI command responses **
|
||||
***************************/
|
||||
|
||||
struct Scsi::Inquiry_response : Genode::Mmio
|
||||
struct Scsi::Inquiry_response : Genode::Mmio<0x24>
|
||||
{
|
||||
/*
|
||||
* Minimum response length is 36 bytes.
|
||||
@ -105,7 +105,7 @@ struct Scsi::Inquiry_response : Genode::Mmio
|
||||
struct Pid : Register_array<0x10, 8, 16, 8> { }; /* product identification */
|
||||
struct Rev : Register_array<0x20, 8, 4, 8> { }; /* product revision level */
|
||||
|
||||
Inquiry_response(addr_t addr) : Mmio(addr) { }
|
||||
Inquiry_response(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
bool sbc() const { return read<Dt>() == 0x00; }
|
||||
bool removable() const { return read<Rm::Rmb>(); }
|
||||
@ -132,7 +132,7 @@ struct Scsi::Inquiry_response : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Scsi::Request_sense_response : Genode::Mmio
|
||||
struct Scsi::Request_sense_response : Genode::Mmio<0x13>
|
||||
{
|
||||
enum { LENGTH = 18 };
|
||||
|
||||
@ -153,7 +153,7 @@ struct Scsi::Request_sense_response : Genode::Mmio
|
||||
struct Fru : Register<0xe, 8> { }; /* field replaceable unit code */
|
||||
struct Sks : Register<0xf, 32> { }; /* sense key specific (3 byte) */
|
||||
|
||||
Request_sense_response(addr_t addr) : Mmio(addr) { }
|
||||
Request_sense_response(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
void dump()
|
||||
{
|
||||
@ -167,14 +167,14 @@ struct Scsi::Request_sense_response : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Scsi::Capacity_response_10 : Genode::Mmio
|
||||
struct Scsi::Capacity_response_10 : Genode::Mmio<0x8>
|
||||
{
|
||||
enum { LENGTH = 8 };
|
||||
|
||||
struct Lba : Register<0x0, 32> { };
|
||||
struct Bs : Register<0x4, 32> { };
|
||||
|
||||
Capacity_response_10(addr_t addr) : Mmio(addr) { }
|
||||
Capacity_response_10(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
uint32_t last_block() const { return be(read<Lba>()); }
|
||||
uint32_t block_size() const { return be(read<Bs>()); }
|
||||
@ -188,14 +188,14 @@ struct Scsi::Capacity_response_10 : Genode::Mmio
|
||||
};
|
||||
|
||||
|
||||
struct Scsi::Capacity_response_16 : Genode::Mmio
|
||||
struct Scsi::Capacity_response_16 : Genode::Mmio<0xc>
|
||||
{
|
||||
enum { LENGTH = 32 };
|
||||
|
||||
struct Lba : Register<0x0, 64> { };
|
||||
struct Bs : Register<0x8, 32> { };
|
||||
|
||||
Capacity_response_16(addr_t addr) : Mmio(addr) { }
|
||||
Capacity_response_16(Byte_range_ptr const &range) : Mmio(range) { }
|
||||
|
||||
uint64_t last_block() const { return be(read<Lba>()); }
|
||||
uint32_t block_size() const { return be(read<Bs>()); }
|
||||
@ -213,7 +213,7 @@ struct Scsi::Capacity_response_16 : Genode::Mmio
|
||||
** CBD 6 byte commands **
|
||||
*************************/
|
||||
|
||||
struct Scsi::Cmd_6 : Genode::Mmio
|
||||
struct Scsi::Cmd_6 : Genode::Mmio<0x6>
|
||||
{
|
||||
enum { LENGTH = 6 };
|
||||
struct Op : Register<0x0, 8> { }; /* SCSI command */
|
||||
@ -221,7 +221,7 @@ struct Scsi::Cmd_6 : Genode::Mmio
|
||||
struct Len : Register<0x4, 8> { }; /* transfer length */
|
||||
struct Ctl : Register<0x5, 8> { }; /* controll */
|
||||
|
||||
Cmd_6(addr_t addr) : Mmio(addr) { memset((void*)addr, 0, LENGTH); }
|
||||
Cmd_6(Byte_range_ptr const &range) : Mmio(range) { memset((void*)base(), 0, LENGTH); }
|
||||
|
||||
void dump()
|
||||
{
|
||||
@ -235,7 +235,7 @@ struct Scsi::Cmd_6 : Genode::Mmio
|
||||
|
||||
struct Scsi::Test_unit_ready : Cmd_6
|
||||
{
|
||||
Test_unit_ready(addr_t addr) : Cmd_6(addr)
|
||||
Test_unit_ready(Byte_range_ptr const &range) : Cmd_6(range)
|
||||
{
|
||||
write<Cmd_6::Op>(Opcode::TEST_UNIT_READY);
|
||||
}
|
||||
@ -244,7 +244,7 @@ struct Scsi::Test_unit_ready : Cmd_6
|
||||
|
||||
struct Scsi::Request_sense : Cmd_6
|
||||
{
|
||||
Request_sense(addr_t addr) : Cmd_6(addr)
|
||||
Request_sense(Byte_range_ptr const &range) : Cmd_6(range)
|
||||
{
|
||||
write<Cmd_6::Op>(Opcode::REQUEST_SENSE);
|
||||
write<Cmd_6::Len>(Request_sense_response::LENGTH);
|
||||
@ -254,7 +254,7 @@ struct Scsi::Request_sense : Cmd_6
|
||||
|
||||
struct Scsi::Inquiry : Cmd_6
|
||||
{
|
||||
Inquiry(addr_t addr) : Cmd_6(addr)
|
||||
Inquiry(Byte_range_ptr const &range) : Cmd_6(range)
|
||||
{
|
||||
write<Cmd_6::Op>(Opcode::INQUIRY);
|
||||
write<Cmd_6::Len>(Inquiry_response::LENGTH);
|
||||
@ -262,7 +262,7 @@ struct Scsi::Inquiry : Cmd_6
|
||||
};
|
||||
|
||||
|
||||
struct Scsi::Start_stop : Genode::Mmio
|
||||
struct Scsi::Start_stop : Genode::Mmio<0x5>
|
||||
{
|
||||
enum { LENGTH = 6 };
|
||||
struct Op : Register<0x0, 8> { }; /* SCSI command */
|
||||
@ -275,9 +275,9 @@ struct Scsi::Start_stop : Genode::Mmio
|
||||
struct St : Bitfield<0, 1> { }; /* start */
|
||||
}; /* flags */
|
||||
|
||||
Start_stop(addr_t addr) : Mmio(addr)
|
||||
Start_stop(Byte_range_ptr const &range) : Mmio(range)
|
||||
{
|
||||
memset((void*)addr, 0, LENGTH);
|
||||
memset((void*)base(), 0, LENGTH);
|
||||
|
||||
write<Op>(Opcode::START_STOP);
|
||||
write<I::Immed>(1);
|
||||
@ -301,7 +301,7 @@ struct Scsi::Start_stop : Genode::Mmio
|
||||
** CBD 10 byte commands **
|
||||
**************************/
|
||||
|
||||
struct Scsi::Cmd_10 : Genode::Mmio
|
||||
struct Scsi::Cmd_10 : Genode::Mmio<0xa>
|
||||
{
|
||||
enum { LENGTH = 10 };
|
||||
struct Op : Register<0x0, 8> { }; /* SCSI command */
|
||||
@ -309,7 +309,7 @@ struct Scsi::Cmd_10 : Genode::Mmio
|
||||
struct Len : Register<0x7, 16> { }; /* transfer length */
|
||||
struct Ctl : Register<0x9, 8> { }; /* controll */
|
||||
|
||||
Cmd_10(addr_t addr) : Mmio(addr) { memset((void*)addr, 0, LENGTH); }
|
||||
Cmd_10(Byte_range_ptr const &range) : Mmio(range) { memset((void*)base(), 0, LENGTH); }
|
||||
|
||||
void dump()
|
||||
{
|
||||
@ -323,7 +323,7 @@ struct Scsi::Cmd_10 : Genode::Mmio
|
||||
|
||||
struct Scsi::Read_capacity_10 : Cmd_10
|
||||
{
|
||||
Read_capacity_10(addr_t addr) : Cmd_10(addr)
|
||||
Read_capacity_10(Byte_range_ptr const &range) : Cmd_10(range)
|
||||
{
|
||||
write<Cmd_10::Op>(Opcode::READ_CAPACITY_10);
|
||||
}
|
||||
@ -332,7 +332,7 @@ struct Scsi::Read_capacity_10 : Cmd_10
|
||||
|
||||
struct Scsi::Io_10 : Cmd_10
|
||||
{
|
||||
Io_10(addr_t addr, uint32_t lba, uint16_t len) : Cmd_10(addr)
|
||||
Io_10(Byte_range_ptr const &range, uint32_t lba, uint16_t len) : Cmd_10(range)
|
||||
{
|
||||
write<Cmd_10::Lba>(be(lba));
|
||||
write<Cmd_10::Len>(be(len));
|
||||
@ -342,7 +342,7 @@ struct Scsi::Io_10 : Cmd_10
|
||||
|
||||
struct Scsi::Read_10 : Io_10
|
||||
{
|
||||
Read_10(addr_t addr, uint32_t lba, uint16_t len) : Io_10(addr, lba, len)
|
||||
Read_10(Byte_range_ptr const &range, uint32_t lba, uint16_t len) : Io_10(range, lba, len)
|
||||
{
|
||||
write<Cmd_10::Op>(Opcode::READ_10);
|
||||
}
|
||||
@ -351,7 +351,7 @@ struct Scsi::Read_10 : Io_10
|
||||
|
||||
struct Scsi::Write_10 : Io_10
|
||||
{
|
||||
Write_10(addr_t addr, uint32_t lba, uint16_t len) : Io_10(addr, lba, len)
|
||||
Write_10(Byte_range_ptr const &range, uint32_t lba, uint16_t len) : Io_10(range, lba, len)
|
||||
{
|
||||
write<Cmd_10::Op>(Opcode::WRITE_10);
|
||||
}
|
||||
@ -362,7 +362,7 @@ struct Scsi::Write_10 : Io_10
|
||||
** CBD 16 long LBA byte commands **
|
||||
***********************************/
|
||||
|
||||
struct Scsi::Cmd_16 : Genode::Mmio
|
||||
struct Scsi::Cmd_16 : Genode::Mmio<0x10>
|
||||
{
|
||||
enum { LENGTH = 16 };
|
||||
struct Op : Register<0x0, 8> { }; /* SCSI command */
|
||||
@ -370,7 +370,7 @@ struct Scsi::Cmd_16 : Genode::Mmio
|
||||
struct Len : Register<0xa, 32> { }; /* transfer length */
|
||||
struct Ctl : Register<0xf, 8> { }; /* controll */
|
||||
|
||||
Cmd_16(addr_t addr) : Mmio(addr) { memset((void*)addr, 0, LENGTH); }
|
||||
Cmd_16(Byte_range_ptr const &range) : Mmio(range) { memset((void*)base(), 0, LENGTH); }
|
||||
|
||||
void dump()
|
||||
{
|
||||
@ -384,7 +384,7 @@ struct Scsi::Cmd_16 : Genode::Mmio
|
||||
|
||||
struct Scsi::Read_capacity_16 : Cmd_16
|
||||
{
|
||||
Read_capacity_16(addr_t addr) : Cmd_16(addr)
|
||||
Read_capacity_16(Byte_range_ptr const &range) : Cmd_16(range)
|
||||
{
|
||||
write<Cmd_16::Op>(Opcode::READ_CAPACITY_16);
|
||||
}
|
||||
@ -393,7 +393,7 @@ struct Scsi::Read_capacity_16 : Cmd_16
|
||||
|
||||
struct Scsi::Io_16 : Cmd_16
|
||||
{
|
||||
Io_16(addr_t addr, uint64_t lba, uint32_t len) : Cmd_16(addr)
|
||||
Io_16(Byte_range_ptr const &range, uint32_t lba, uint16_t len) : Cmd_16(range)
|
||||
{
|
||||
write<Cmd_16::Lba>(be(lba));
|
||||
write<Cmd_16::Len>(be(len));
|
||||
@ -403,7 +403,7 @@ struct Scsi::Io_16 : Cmd_16
|
||||
|
||||
struct Scsi::Read_16 : Io_16
|
||||
{
|
||||
Read_16(addr_t addr, uint64_t lba, uint32_t len) : Io_16(addr, lba, len)
|
||||
Read_16(Byte_range_ptr const &range, uint32_t lba, uint16_t len) : Io_16(range, lba, len)
|
||||
{
|
||||
write<Cmd_16::Op>(Opcode::READ_16);
|
||||
}
|
||||
@ -412,7 +412,7 @@ struct Scsi::Read_16 : Io_16
|
||||
|
||||
struct Scsi::Write_16 : Io_16
|
||||
{
|
||||
Write_16(addr_t addr, uint64_t lba, uint32_t len) : Io_16(addr, lba, len)
|
||||
Write_16(Byte_range_ptr const &range, uint32_t lba, uint16_t len) : Io_16(range, lba, len)
|
||||
{
|
||||
write<Cmd_16::Op>(Opcode::WRITE_16);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ struct Virtdev_rom::Main
|
||||
Sliced_heap _heap { _env.ram(), _env.rm() };
|
||||
Virtdev_rom::Root _root { _env, _heap, _ds };
|
||||
|
||||
struct Device : public Attached_mmio
|
||||
struct Device : public Attached_mmio<0xc>
|
||||
{
|
||||
struct Magic : Register<0x000, 32> { };
|
||||
struct Id : Register<0x008, 32> {
|
||||
@ -108,8 +108,8 @@ struct Virtdev_rom::Main
|
||||
};
|
||||
};
|
||||
|
||||
Device(Env &env, addr_t base, size_t size)
|
||||
: Attached_mmio(env, base, size, false) { }
|
||||
Device(Env &env, Byte_range_ptr const &range)
|
||||
: Attached_mmio(env, range, false) { }
|
||||
};
|
||||
|
||||
static char const *_name_for_id(unsigned id)
|
||||
@ -138,7 +138,7 @@ struct Virtdev_rom::Main
|
||||
|
||||
for (size_t idx = 0; idx < NUM_VIRTIO_TRANSPORTS; ++idx) {
|
||||
addr_t addr = BASE_ADDRESS + idx * DEVICE_SIZE;
|
||||
Device device { _env, BASE_ADDRESS + idx * DEVICE_SIZE, DEVICE_SIZE };
|
||||
Device device { _env, {(char *)(BASE_ADDRESS + idx * DEVICE_SIZE), DEVICE_SIZE} };
|
||||
|
||||
if (device.read<Device::Magic>() != VIRTIO_MMIO_MAGIC) {
|
||||
warning("Found non VirtIO MMIO device @ ", Hex(addr));
|
||||
|
@ -96,7 +96,7 @@ class Block::Ahdi : public Partition_table
|
||||
{
|
||||
bool any_partition_valid = false;
|
||||
|
||||
Root_sector const root = *sector.addr<Root_sector const *>();
|
||||
Root_sector const root = *(Root_sector const *)sector.buffer().start;
|
||||
for (unsigned i = 0; i < MAX_PARTITIONS; i++)
|
||||
if (root.partitions[i].valid())
|
||||
any_partition_valid = true;
|
||||
@ -107,7 +107,7 @@ class Block::Ahdi : public Partition_table
|
||||
template <typename FUNC>
|
||||
void _parse_ahdi(Sync_read const §or, FUNC const &fn)
|
||||
{
|
||||
Root_sector &root = *sector.addr<Root_sector *>();
|
||||
Root_sector &root = *(Root_sector *)sector.buffer().start;
|
||||
|
||||
for (unsigned i = 0; i < MAX_PARTITIONS; i++) {
|
||||
Partition_record const &part = root.partitions[i];
|
||||
|
@ -63,11 +63,11 @@ class Block::Sync_read : Noncopyable
|
||||
|
||||
private:
|
||||
|
||||
Handler &_handler;
|
||||
Allocator &_alloc;
|
||||
size_t _size { 0 };
|
||||
void *_buffer { nullptr };
|
||||
bool _success { false };
|
||||
Handler &_handler;
|
||||
Allocator &_alloc;
|
||||
size_t _size { 0 };
|
||||
Constructible<Byte_range_ptr> _buffer { };
|
||||
bool _success { false };
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
@ -100,7 +100,7 @@ class Block::Sync_read : Noncopyable
|
||||
|
||||
~Sync_read()
|
||||
{
|
||||
_alloc.free(_buffer, _size);
|
||||
_alloc.free(_buffer->start, _size);
|
||||
}
|
||||
|
||||
bool success() const { return _success; }
|
||||
@ -108,8 +108,8 @@ class Block::Sync_read : Noncopyable
|
||||
void consume_read_result(Block_connection::Job &, off_t offset,
|
||||
char const *src, size_t length)
|
||||
{
|
||||
_buffer = _alloc.alloc(length);
|
||||
memcpy((char *)_buffer + offset, src, length);
|
||||
_buffer.construct((char *)_alloc.alloc(length), length);
|
||||
memcpy(_buffer->start + offset, src, length);
|
||||
_size += length;
|
||||
}
|
||||
|
||||
@ -126,8 +126,7 @@ class Block::Sync_read : Noncopyable
|
||||
_success = success;
|
||||
}
|
||||
|
||||
template <typename T> T addr() const {
|
||||
return reinterpret_cast<T>(_buffer); }
|
||||
Byte_range_ptr const &buffer() const { return *_buffer; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
/**
|
||||
* DCE uuid struct
|
||||
*/
|
||||
struct Uuid : Mmio
|
||||
struct Uuid : Mmio<16>
|
||||
{
|
||||
struct Time_low : Register<0, 32> { };
|
||||
struct Time_mid : Register<4, 16> { };
|
||||
@ -72,7 +72,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
struct Node : Register_array<10, 8, 6, 8> { };
|
||||
|
||||
Uuid() = delete;
|
||||
Uuid(addr_t base) : Mmio(base) { };
|
||||
using Mmio::Mmio;
|
||||
|
||||
unsigned time_low() const { return read<Time_low>(); }
|
||||
|
||||
@ -98,7 +98,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
/**
|
||||
* GUID parition table header
|
||||
*/
|
||||
struct Gpt_hdr : Mmio
|
||||
struct Gpt_hdr : Mmio<92>
|
||||
{
|
||||
struct Sig : Register<0, 64> { }; /* identifies GUID Partition Table */
|
||||
struct Revision : Register<8, 32> { }; /* GPT specification revision */
|
||||
@ -112,7 +112,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
struct Part_lba_start : Register<40, 64> { }; /* first LBA usable for partitions */
|
||||
struct Part_lba_end : Register<48, 64> { }; /* last LBA usable for partitions */
|
||||
|
||||
Uuid guid() { return Uuid(base() + 56); } /* GUID to identify the disk */
|
||||
Uuid guid() { return Uuid(range_at(56)); } /* GUID to identify the disk */
|
||||
|
||||
struct Gpe_lba : Register<72, 64> { }; /* first LBA of GPE array */
|
||||
struct Entries : Register<80, 32> { }; /* number of entries in GPE array */
|
||||
@ -120,7 +120,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
struct Gpe_crc : Register<88, 32> { }; /* CRC32 of GPE array */
|
||||
|
||||
Gpt_hdr() = delete;
|
||||
Gpt_hdr(addr_t base) : Mmio(base) { };
|
||||
using Mmio::Mmio;
|
||||
|
||||
uint64_t part_lba_start() const { return read<Part_lba_start>(); }
|
||||
uint64_t part_lba_end() const { return read<Part_lba_end>(); }
|
||||
@ -190,7 +190,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
size_t length = entries() * entry_size();
|
||||
Sync_read gpe(handler, alloc, gpe_lba(), length / block_size);
|
||||
if (!gpe.success()
|
||||
|| crc32(gpe.addr<addr_t>(), length) != read<Gpe_crc>())
|
||||
|| crc32((addr_t)gpe.buffer().start, length) != read<Gpe_crc>())
|
||||
return false;
|
||||
|
||||
if (check_primary) {
|
||||
@ -199,7 +199,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
if (!backup_hdr.success())
|
||||
return false;
|
||||
|
||||
Gpt_hdr backup(backup_hdr.addr<addr_t>());
|
||||
Gpt_hdr backup(backup_hdr.buffer());
|
||||
if (!backup.valid(handler, alloc, block_size, false))
|
||||
warning("Backup GPT header is corrupted");
|
||||
}
|
||||
@ -220,12 +220,12 @@ class Block::Gpt : public Block::Partition_table
|
||||
/**
|
||||
* GUID partition entry format
|
||||
*/
|
||||
struct Gpt_entry : Mmio
|
||||
struct Gpt_entry : Mmio<56 + 36 * 2>
|
||||
{
|
||||
enum { NAME_LEN = 36 };
|
||||
|
||||
Uuid type() const { return Uuid(base()); } /* partition type GUID */
|
||||
Uuid guid() const { return Uuid(base()+ Uuid::size()); } /* unique partition GUID */
|
||||
Uuid type() const { return Uuid(range()); } /* partition type GUID */
|
||||
Uuid guid() const { return Uuid(range_at(Uuid::size())); } /* unique partition GUID */
|
||||
|
||||
struct Lba_start : Register<32, 64> { }; /* start of partition */
|
||||
struct Lba_end : Register<40, 64> { }; /* end of partition */
|
||||
@ -233,7 +233,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
struct Name : Register_array<56, 16, NAME_LEN, 16> { }; /* partition name in UNICODE-16 */
|
||||
|
||||
Gpt_entry() = delete;
|
||||
Gpt_entry(addr_t base) : Mmio(base) { }
|
||||
using Mmio::Mmio;
|
||||
|
||||
uint64_t lba_start() const { return read<Lba_start>(); }
|
||||
uint64_t lba_end() const { return read<Lba_end>(); }
|
||||
@ -340,7 +340,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
uint64_t used = 0;
|
||||
|
||||
for (uint32_t i = 0; i < num; i++) {
|
||||
Gpt_entry const e(entries.base() + i * header.entry_size());
|
||||
Gpt_entry const e(entries.range_at(i * header.entry_size()));
|
||||
|
||||
if (!e.valid()) { continue; }
|
||||
|
||||
@ -364,7 +364,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
gpt.entries() * gpt.entry_size() / _info.block_size);
|
||||
if (!entry_array.success())
|
||||
return false;
|
||||
Gpt_entry entries(entry_array.addr<addr_t>());
|
||||
Gpt_entry entries(entry_array.buffer());
|
||||
|
||||
_gpt_part_lba_end = gpt.part_lba_end();
|
||||
_gpt_total = (gpt.part_lba_end() - gpt.part_lba_start()) + 1;
|
||||
@ -372,7 +372,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
|
||||
for (int i = 0; i < MAX_PARTITIONS; i++) {
|
||||
|
||||
Gpt_entry e(entries.base() + i * gpt.entry_size());
|
||||
Gpt_entry e(entries.range_at(i * gpt.entry_size()));
|
||||
|
||||
if (!e.valid())
|
||||
continue;
|
||||
@ -404,7 +404,7 @@ class Block::Gpt : public Block::Partition_table
|
||||
if (!s.success())
|
||||
return false;
|
||||
|
||||
Gpt_hdr gpt_hdr(s.addr<addr_t>());
|
||||
Gpt_hdr gpt_hdr(s.buffer());
|
||||
|
||||
if (!_parse_gpt(gpt_hdr))
|
||||
return false;
|
||||
|
@ -52,7 +52,7 @@ class Block::Mbr : public Partition_table
|
||||
/**
|
||||
* Partition table entry format
|
||||
*/
|
||||
struct Partition_record : Mmio
|
||||
struct Partition_record : Mmio<16>
|
||||
{
|
||||
struct Type : Register<4, 8>
|
||||
{
|
||||
@ -66,8 +66,7 @@ class Block::Mbr : public Partition_table
|
||||
|
||||
Partition_record() = delete;
|
||||
|
||||
Partition_record(addr_t base)
|
||||
: Mmio(base) { }
|
||||
using Mmio::Mmio;
|
||||
|
||||
bool valid() const { return read<Type>() != Type::INVALID; }
|
||||
bool extended() const { return read<Type>() == Type::EXTENTED_CHS ||
|
||||
@ -83,7 +82,7 @@ class Block::Mbr : public Partition_table
|
||||
/**
|
||||
* Master/Extented boot record format
|
||||
*/
|
||||
struct Boot_record : Mmio
|
||||
struct Boot_record : Mmio<512>
|
||||
{
|
||||
struct Magic : Register<510, 16>
|
||||
{
|
||||
@ -92,7 +91,7 @@ class Block::Mbr : public Partition_table
|
||||
|
||||
Boot_record() = delete;
|
||||
|
||||
Boot_record(addr_t base) : Mmio(base) { }
|
||||
using Mmio::Mmio;
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
@ -100,9 +99,9 @@ class Block::Mbr : public Partition_table
|
||||
return read<Magic>() == Magic::NUMBER;
|
||||
}
|
||||
|
||||
addr_t record(unsigned index) const
|
||||
Byte_range_ptr record(unsigned index) const
|
||||
{
|
||||
return base() + 446 + (index * Partition_record::size());
|
||||
return range_at(446 + (index * Partition_record::size()));
|
||||
}
|
||||
};
|
||||
|
||||
@ -113,7 +112,7 @@ class Block::Mbr : public Partition_table
|
||||
template <typename FUNC>
|
||||
void _parse_extended(Partition_record const &record, FUNC const &f) const
|
||||
{
|
||||
Reconstructible<Partition_record const> r(record.base());
|
||||
Reconstructible<Partition_record const> r(record.range());
|
||||
unsigned lba = r->lba();
|
||||
unsigned last_lba = 0;
|
||||
|
||||
@ -124,7 +123,7 @@ class Block::Mbr : public Partition_table
|
||||
if (!s.success())
|
||||
return;
|
||||
|
||||
Boot_record const ebr(s.addr<addr_t>());
|
||||
Boot_record const ebr(s.buffer());
|
||||
if (!ebr.valid())
|
||||
return;
|
||||
|
||||
@ -188,7 +187,7 @@ class Block::Mbr : public Partition_table
|
||||
return Parse_result::NO_MBR;
|
||||
|
||||
/* check for MBR */
|
||||
Boot_record const mbr(s.addr<addr_t>());
|
||||
Boot_record const mbr(s.buffer());
|
||||
if (!mbr.valid())
|
||||
return Parse_result::NO_MBR;
|
||||
|
||||
|
@ -54,7 +54,7 @@ class Block::Partition_table : Interface, Noncopyable
|
||||
enum { BYTES = 4096 };
|
||||
Sync_read fs(_handler, _alloc, lba, BYTES / _info.block_size);
|
||||
if (fs.success())
|
||||
return Fs::probe(fs.addr<uint8_t*>(), BYTES);
|
||||
return Fs::probe((uint8_t *)fs.buffer().start, BYTES);
|
||||
else
|
||||
return Fs::Type();
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
/* Genode includes */
|
||||
#include <os/attached_mmio.h>
|
||||
|
||||
class M4if : Genode::Attached_mmio
|
||||
class M4if : Genode::Attached_mmio<0x11c>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -58,8 +58,8 @@ class M4if : Genode::Attached_mmio
|
||||
|
||||
public:
|
||||
|
||||
M4if(Genode::Env &env, Genode::addr_t base, Genode::size_t size)
|
||||
: Genode::Attached_mmio(env, base, size) { }
|
||||
M4if(Genode::Env &env, Genode::Byte_range_ptr const &range)
|
||||
: Attached_mmio(env, range) { }
|
||||
|
||||
void set_region0(Genode::addr_t addr, Genode::size_t size)
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ class Main
|
||||
KERNEL_OFFSET, Machine_type(MACHINE_QSB),
|
||||
Board_revision(BOARD_QSB),
|
||||
_heap, _exception_handler };
|
||||
M4if _m4if { _env, Imx53::M4IF_BASE, Imx53::M4IF_SIZE };
|
||||
M4if _m4if { _env, {(char *)Imx53::M4IF_BASE, Imx53::M4IF_SIZE} };
|
||||
Serial_driver _serial { _env.ram(), _env.rm() };
|
||||
Block_driver _block { _env, _config.xml(), _heap, _vm };
|
||||
|
||||
|
@ -26,7 +26,7 @@ class Mmio_big_endian_access
|
||||
|
||||
private:
|
||||
|
||||
addr_t const _base;
|
||||
Byte_range_ptr const _range;
|
||||
|
||||
/**
|
||||
* Write '_ACCESS_T' typed 'value' to MMIO base + 'offset'
|
||||
@ -34,8 +34,7 @@ class Mmio_big_endian_access
|
||||
template <typename ACCESS_T>
|
||||
inline void _write(off_t const offset, ACCESS_T const value)
|
||||
{
|
||||
addr_t const dst = _base + offset;
|
||||
*(ACCESS_T volatile *)dst = host_to_big_endian(value);
|
||||
*(ACCESS_T volatile *)(_range.start + offset) = host_to_big_endian(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,30 +43,38 @@ class Mmio_big_endian_access
|
||||
template <typename ACCESS_T>
|
||||
inline ACCESS_T _read(off_t const &offset) const
|
||||
{
|
||||
addr_t const dst = _base + offset;
|
||||
ACCESS_T const value = *(ACCESS_T volatile *)dst;
|
||||
return host_to_big_endian(value);
|
||||
return host_to_big_endian(*(ACCESS_T volatile *)(_range.start + offset));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Mmio_big_endian_access(addr_t const base) : _base(base) { }
|
||||
Mmio_big_endian_access(Byte_range_ptr const &range) : _range(range.start, range.num_bytes) { }
|
||||
|
||||
addr_t base() const { return _base; }
|
||||
Byte_range_ptr range_at(off_t offset) const
|
||||
{
|
||||
return {_range.start + offset, _range.num_bytes - offset};
|
||||
}
|
||||
|
||||
Byte_range_ptr range() const { return range_at(0); }
|
||||
|
||||
addr_t base() const { return (addr_t)range().start; }
|
||||
};
|
||||
|
||||
|
||||
template <size_t MMIO_SIZE>
|
||||
struct Mmio : Mmio_big_endian_access,
|
||||
Register_set<Mmio_big_endian_access>
|
||||
Register_set<Mmio_big_endian_access, MMIO_SIZE>
|
||||
{
|
||||
Mmio(addr_t const base)
|
||||
static constexpr size_t SIZE = MMIO_SIZE;
|
||||
|
||||
Mmio(Byte_range_ptr const &range)
|
||||
:
|
||||
Mmio_big_endian_access(base),
|
||||
Register_set(*static_cast<Mmio_big_endian_access *>(this)) { }
|
||||
Mmio_big_endian_access(range),
|
||||
Register_set<Mmio_big_endian_access, SIZE>(*static_cast<Mmio_big_endian_access *>(this)) { }
|
||||
};
|
||||
|
||||
|
||||
struct Fdt_header : Mmio
|
||||
struct Fdt_header : Mmio<10*4>
|
||||
{
|
||||
struct Magic : Register<0x0, 32> {};
|
||||
struct Totalsize : Register<0x4, 32> {};
|
||||
@ -81,19 +88,15 @@ struct Fdt_header : Mmio
|
||||
struct Size_dt_struct : Register<0x24, 32> {};
|
||||
|
||||
using Mmio::Mmio;
|
||||
|
||||
enum { SIZE = 10*4 };
|
||||
};
|
||||
|
||||
|
||||
struct Fdt_reserve_entry : Mmio
|
||||
struct Fdt_reserve_entry : Mmio<2*8>
|
||||
{
|
||||
struct Address : Register<0, 64> {};
|
||||
struct Size : Register<8, 64> {};
|
||||
|
||||
using Mmio::Mmio;
|
||||
|
||||
enum { SIZE = 2*8 };
|
||||
};
|
||||
|
||||
|
||||
@ -106,35 +109,37 @@ enum Fdt_tokens {
|
||||
};
|
||||
|
||||
|
||||
struct Fdt_token : Mmio
|
||||
template <size_t SIZE>
|
||||
struct Fdt_token_tpl : Mmio<SIZE>
|
||||
{
|
||||
struct Type : Register<0, 32> {};
|
||||
using Base = Mmio<SIZE>;
|
||||
|
||||
Fdt_token(addr_t const base, Fdt_tokens type)
|
||||
struct Type : Base::template Register<0, 32> {};
|
||||
|
||||
Fdt_token_tpl(Byte_range_ptr const &range, Fdt_tokens type)
|
||||
:
|
||||
Mmio(base)
|
||||
Base(range)
|
||||
{
|
||||
write<Type>(type);
|
||||
Base::template write<Type>(type);
|
||||
}
|
||||
|
||||
enum { SIZE = 4 };
|
||||
};
|
||||
|
||||
|
||||
struct Fdt_prop : Fdt_token
|
||||
using Fdt_token = Fdt_token_tpl<0x4>;
|
||||
|
||||
|
||||
struct Fdt_prop : Fdt_token_tpl<Fdt_token::SIZE + 2*4>
|
||||
{
|
||||
struct Len : Register<4, 32> {};
|
||||
struct Nameoff : Register<8, 32> {};
|
||||
|
||||
Fdt_prop(addr_t base, uint32_t len, uint32_t name_offset)
|
||||
Fdt_prop(Byte_range_ptr const &range, uint32_t len, uint32_t name_offset)
|
||||
:
|
||||
Fdt_token(base, FDT_PROP)
|
||||
Fdt_token_tpl(range, FDT_PROP)
|
||||
{
|
||||
write<Fdt_prop::Len>(len);
|
||||
write<Fdt_prop::Nameoff>(name_offset);
|
||||
}
|
||||
|
||||
enum { SIZE = Fdt_token::SIZE + 2*4 };
|
||||
};
|
||||
|
||||
|
||||
@ -220,20 +225,20 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
|
||||
auto node = [&] (auto const & name, auto const & fn)
|
||||
{
|
||||
Fdt_token start(_buffer.addr+off, FDT_BEGIN_NODE);
|
||||
Fdt_token start({(char *)_buffer.addr+off, _buffer.size-off}, FDT_BEGIN_NODE);
|
||||
off += Fdt_token::SIZE;
|
||||
_buffer.write(off, name.string(), name.length());
|
||||
off += (uint32_t)name.length();
|
||||
off = align_addr(off, 2);
|
||||
fn();
|
||||
Fdt_token end(_buffer.addr+off, FDT_END_NODE);
|
||||
Fdt_token end({(char *)_buffer.addr+off, _buffer.size-off}, FDT_END_NODE);
|
||||
off += Fdt_token::SIZE;
|
||||
};
|
||||
|
||||
auto property = [&] (auto const & name, auto const & val)
|
||||
{
|
||||
_dict.add(name);
|
||||
Fdt_prop prop(_buffer.addr+off, (uint32_t)val.length(),
|
||||
Fdt_prop prop({(char *)_buffer.addr+off, _buffer.size-off}, (uint32_t)val.length(),
|
||||
_dict.offset(name));
|
||||
off += Fdt_prop::SIZE;
|
||||
val.write(off, _buffer);
|
||||
@ -366,7 +371,7 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
});
|
||||
});
|
||||
|
||||
Fdt_token end(_buffer.addr+off, FDT_END);
|
||||
Fdt_token end({(char *)_buffer.addr+off, _buffer.size-off}, FDT_END);
|
||||
off += Fdt_token::SIZE;
|
||||
}
|
||||
|
||||
@ -374,7 +379,7 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
void Vmm::Fdt_generator::generate(Config const & config,
|
||||
void * initrd_start, size_t initrd_size)
|
||||
{
|
||||
Fdt_header header(_buffer.addr);
|
||||
Fdt_header header({(char *)_buffer.addr, _buffer.size});
|
||||
header.write<Fdt_header::Magic>(FDT_MAGIC);
|
||||
header.write<Fdt_header::Version>(FDT_VERSION);
|
||||
header.write<Fdt_header::Last_comp_version>(FDT_COMP_VERSION);
|
||||
@ -382,7 +387,7 @@ void Vmm::Fdt_generator::generate(Config const & config,
|
||||
|
||||
uint32_t off = Fdt_header::SIZE;
|
||||
header.write<Fdt_header::Off_mem_rsvmap>(off);
|
||||
Fdt_reserve_entry memory(_buffer.addr+off);
|
||||
Fdt_reserve_entry memory({(char *)_buffer.addr+off, _buffer.size-off});
|
||||
memory.write<Fdt_reserve_entry::Address>(0);
|
||||
memory.write<Fdt_reserve_entry::Size>(0);
|
||||
|
||||
@ -391,7 +396,7 @@ void Vmm::Fdt_generator::generate(Config const & config,
|
||||
|
||||
_generate_tree(off, config, initrd_start, initrd_size);
|
||||
|
||||
header.write<Fdt_header::Size_dt_struct>(off-Fdt_header::SIZE-Fdt_reserve_entry::SIZE);
|
||||
header.write<Fdt_header::Size_dt_struct>((uint32_t)(off-Fdt_header::SIZE-Fdt_reserve_entry::SIZE));
|
||||
|
||||
header.write<Fdt_header::Off_dt_strings>(off);
|
||||
header.write<Fdt_header::Size_dt_strings>(_dict.length());
|
||||
|
@ -21,29 +21,34 @@ class Ram {
|
||||
|
||||
private:
|
||||
|
||||
Genode::addr_t const _base;
|
||||
Genode::size_t const _size;
|
||||
Genode::addr_t const _local;
|
||||
using Byte_range_ptr = Genode::Byte_range_ptr;
|
||||
using addr_t = Genode::addr_t;
|
||||
using size_t = Genode::size_t;
|
||||
|
||||
addr_t const _guest_base;
|
||||
Byte_range_ptr const _local_range;
|
||||
|
||||
public:
|
||||
|
||||
Ram(Genode::addr_t const addr,
|
||||
Genode::size_t const sz,
|
||||
Genode::addr_t const local)
|
||||
: _base(addr), _size(sz), _local(local) { }
|
||||
Ram(addr_t guest_base, Byte_range_ptr const &local_range)
|
||||
: _guest_base(guest_base), _local_range(local_range.start, local_range.num_bytes) { }
|
||||
|
||||
Genode::addr_t base() const { return _base; }
|
||||
Genode::size_t size() const { return _size; }
|
||||
Genode::addr_t local() const { return _local; }
|
||||
size_t size() const { return _local_range.num_bytes; }
|
||||
addr_t guest_base() const { return _guest_base; }
|
||||
addr_t local_base() const { return (addr_t)_local_range.start; }
|
||||
|
||||
Genode::addr_t local_address(Genode::addr_t guest, Genode::size_t size)
|
||||
Byte_range_ptr to_local_range(Byte_range_ptr const &guest_range)
|
||||
{
|
||||
if (guest < _base || guest >= _base + _size ||
|
||||
size == 0 || guest + size >= _base + _size)
|
||||
addr_t guest_base = (addr_t)guest_range.start;
|
||||
if (guest_base < _guest_base ||
|
||||
guest_base >= _guest_base + _local_range.num_bytes ||
|
||||
guest_range.num_bytes == 0 ||
|
||||
guest_base + guest_range.num_bytes >= _guest_base + _local_range.num_bytes)
|
||||
throw Vmm::Exception("Invalid guest physical address: ",
|
||||
Genode::Hex(guest), " size: ", Genode::Hex(size));
|
||||
Genode::Hex(guest_base), " size: ", Genode::Hex(guest_range.num_bytes));
|
||||
|
||||
return _local + (guest - _base);
|
||||
Genode::off_t offset = guest_base - _guest_base;
|
||||
return {_local_range.start + offset, guest_range.num_bytes};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,8 +103,7 @@ class Vmm::Virtio_block_request
|
||||
|
||||
template <typename T>
|
||||
T * _desc_addr(Descriptor const & desc) const {
|
||||
return (T*) _ram.local_address((addr_t)desc.address(),
|
||||
desc.length()); }
|
||||
return (T*) _ram.to_local_range({(char *)desc.address(), desc.length()}).start; }
|
||||
|
||||
Index _request_idx;
|
||||
Descriptor _request { _array.get(_request_idx) };
|
||||
|
@ -34,11 +34,11 @@ class Vmm::Virtio_console : public Virtio_device<Virtio_split_queue, 2>
|
||||
{
|
||||
Genode::Mutex::Guard guard(_mutex);
|
||||
|
||||
auto read = [&] (addr_t data, size_t size)
|
||||
auto read = [&] (Byte_range_ptr const &data)
|
||||
{
|
||||
if (!_terminal.avail()) return 0ul;
|
||||
|
||||
size_t length = _terminal.read((void *)data, size);
|
||||
size_t length = _terminal.read((void *)data.start, data.num_bytes);
|
||||
return length;
|
||||
};
|
||||
|
||||
@ -52,10 +52,10 @@ class Vmm::Virtio_console : public Virtio_device<Virtio_split_queue, 2>
|
||||
{
|
||||
if (idx != TX) return;
|
||||
|
||||
auto write = [&] (addr_t data, size_t size)
|
||||
auto write = [&] (Byte_range_ptr const &data)
|
||||
{
|
||||
_terminal.write((void *)data, size);
|
||||
return size;
|
||||
_terminal.write((void *)data.start, data.num_bytes);
|
||||
return data.num_bytes;
|
||||
};
|
||||
|
||||
if (_queue[TX]->notify(write))
|
||||
|
@ -73,21 +73,24 @@ class Vmm::Virtio_split_queue
|
||||
using Descriptor_index = Index<MAX_SIZE_LOG2>;
|
||||
|
||||
|
||||
struct Queue_base : Mmio
|
||||
template <size_t SIZE>
|
||||
struct Queue_base : Mmio<SIZE>
|
||||
{
|
||||
using Base = Mmio<SIZE>;
|
||||
|
||||
uint16_t const max;
|
||||
|
||||
Queue_base(addr_t base, uint16_t max)
|
||||
: Mmio(base), max(max) {}
|
||||
Queue_base(Byte_range_ptr const &range, uint16_t max)
|
||||
: Base(range), max(max) {}
|
||||
|
||||
struct Flags : Register<0x0, 16> { };
|
||||
struct Idx : Register<0x2, 16> { };
|
||||
struct Flags : Base::template Register<0x0, 16> { };
|
||||
struct Idx : Base::template Register<0x2, 16> { };
|
||||
|
||||
Ring_index current() { return read<Idx>(); }
|
||||
Ring_index current() { return Base::template read<Idx>(); }
|
||||
};
|
||||
|
||||
|
||||
struct Avail_queue : Queue_base
|
||||
struct Avail_queue : Queue_base<0x4 + MAX_SIZE * 2>
|
||||
{
|
||||
using Queue_base::Queue_base;
|
||||
|
||||
@ -105,7 +108,7 @@ class Vmm::Virtio_split_queue
|
||||
} _avail;
|
||||
|
||||
|
||||
struct Used_queue : Queue_base
|
||||
struct Used_queue : Queue_base<0x4 + MAX_SIZE * 8>
|
||||
{
|
||||
using Queue_base::Queue_base;
|
||||
|
||||
@ -129,7 +132,7 @@ class Vmm::Virtio_split_queue
|
||||
} _used;
|
||||
|
||||
|
||||
struct Descriptor : Mmio
|
||||
struct Descriptor : Mmio<0x10>
|
||||
{
|
||||
using Mmio::Mmio;
|
||||
|
||||
@ -154,19 +157,24 @@ class Vmm::Virtio_split_queue
|
||||
|
||||
struct Descriptor_array
|
||||
{
|
||||
size_t const elem_size { 16 };
|
||||
unsigned const max;
|
||||
addr_t const start;
|
||||
size_t const elem_size { 16 };
|
||||
unsigned const max;
|
||||
Byte_range_ptr const guest_range;
|
||||
Byte_range_ptr const local_range;
|
||||
|
||||
Descriptor_array(Ram & ram, addr_t base, unsigned const max)
|
||||
:
|
||||
max(max),
|
||||
start(ram.local_address(base, max * elem_size)) {}
|
||||
guest_range((char *)base, max * elem_size),
|
||||
local_range(
|
||||
ram.to_local_range(guest_range).start,
|
||||
ram.to_local_range(guest_range).num_bytes) {}
|
||||
|
||||
Descriptor get(Descriptor_index idx)
|
||||
{
|
||||
if (idx.idx() >= max) error("Descriptor_index out of bounds");
|
||||
return Descriptor(start + (elem_size * idx.idx()));
|
||||
off_t offset = elem_size * idx.idx();
|
||||
return Descriptor({local_range.start + offset, local_range.num_bytes - offset});
|
||||
}
|
||||
} _descriptors;
|
||||
|
||||
@ -182,8 +190,8 @@ class Vmm::Virtio_split_queue
|
||||
uint16_t const queue_num,
|
||||
Ram & ram)
|
||||
:
|
||||
_avail(ram.local_address(driver_area, 6+2*queue_num), queue_num),
|
||||
_used(ram.local_address(device_area, 6+8*queue_num), queue_num),
|
||||
_avail(ram.to_local_range({(char *)driver_area, 6+2*(size_t)queue_num}), queue_num),
|
||||
_used(ram.to_local_range({(char *)device_area, 6+8*(size_t)queue_num}), queue_num),
|
||||
_descriptors(ram, descriptor_area, queue_num),
|
||||
_ram(ram) { }
|
||||
|
||||
@ -205,8 +213,7 @@ class Vmm::Virtio_split_queue
|
||||
if (!address || !size) { break; }
|
||||
|
||||
try {
|
||||
addr_t data = _ram.local_address((addr_t)address, size);
|
||||
size_t consumed = func(data, size);
|
||||
size_t consumed = func(_ram.to_local_range({(char *)address, size}));
|
||||
if (!consumed) { break; }
|
||||
_used.add(_cur_idx, id, consumed);
|
||||
written = true;
|
||||
|
@ -44,7 +44,7 @@ void Vmm::Virtio_gpu_queue::notify(Virtio_gpu_device & dev)
|
||||
void Vmm::Virtio_gpu_control_request::_get_display_info()
|
||||
{
|
||||
Framebuffer::Mode mode = _device.resize();
|
||||
Display_info_response dir { _desc_addr(1) };
|
||||
Display_info_response dir { _desc_range(1) };
|
||||
memset((void*)dir.base(), 0, Display_info_response::SIZE);
|
||||
dir.write<Control_header::Type>(Control_header::Type::OK_DISPLAY_INFO);
|
||||
|
||||
@ -59,8 +59,8 @@ void Vmm::Virtio_gpu_control_request::_get_display_info()
|
||||
|
||||
void Vmm::Virtio_gpu_control_request::_resource_create_2d()
|
||||
{
|
||||
Resource_create_2d c2d { _desc_addr(0) };
|
||||
Control_header response { _desc_addr(1) };
|
||||
Resource_create_2d c2d { _desc_range(0) };
|
||||
Control_header response { _desc_range(1) };
|
||||
|
||||
if (c2d.read<Resource_create_2d::Format>() !=
|
||||
Resource_create_2d::Format::B8G8R8X8) {
|
||||
@ -90,8 +90,8 @@ void Vmm::Virtio_gpu_control_request::_resource_delete()
|
||||
using Resource = Virtio_gpu_device::Resource;
|
||||
using Scanout = Resource::Scanout;
|
||||
|
||||
Resource_unref rur { _desc_addr(0) };
|
||||
Control_header response { _desc_addr(1) };
|
||||
Resource_unref rur { _desc_range(0) };
|
||||
Control_header response { _desc_range(1) };
|
||||
|
||||
response.write<Control_header::Type>(Control_header::Type::ERR_INVALID_RESOURCE_ID);
|
||||
uint32_t id = rur.read<Resource_unref::Resource_id>();
|
||||
@ -113,9 +113,9 @@ void Vmm::Virtio_gpu_control_request::_resource_attach_backing()
|
||||
using Resource = Virtio_gpu_device::Resource;
|
||||
using Entry = Resource_attach_backing::Memory_entry;
|
||||
|
||||
Resource_attach_backing rab { _desc_addr(0) };
|
||||
addr_t entry_base { _desc_addr(1) };
|
||||
Control_header response { _desc_addr(2) };
|
||||
Resource_attach_backing rab { _desc_range(0) };
|
||||
Byte_range_ptr entry_range { _desc_range(1) };
|
||||
Control_header response { _desc_range(2) };
|
||||
|
||||
response.write<Control_header::Type>(Control_header::Type::ERR_INVALID_RESOURCE_ID);
|
||||
uint32_t id = rab.read<Resource_attach_backing::Resource_id>();
|
||||
@ -127,10 +127,11 @@ void Vmm::Virtio_gpu_control_request::_resource_attach_backing()
|
||||
|
||||
try {
|
||||
for (unsigned i = 0; i < nr; i++) {
|
||||
Entry entry(entry_base+i*Entry::SIZE);
|
||||
off_t offset = i*Entry::SIZE;
|
||||
Entry entry({entry_range.start + offset, entry_range.num_bytes - offset});
|
||||
size_t sz = entry.read<Entry::Length>();
|
||||
addr_t off = _device._ram.local_address((addr_t)entry.read<Entry::Address>(), sz)
|
||||
- _device._ram.local();
|
||||
addr_t off = (addr_t)_device._ram.to_local_range({(char *)entry.read<Entry::Address>(), sz}).start
|
||||
- _device._ram.local_base();
|
||||
res.attach(off, sz);
|
||||
}
|
||||
response.write<Control_header::Type>(Control_header::Type::OK_NO_DATA);
|
||||
@ -143,8 +144,8 @@ void Vmm::Virtio_gpu_control_request::_resource_attach_backing()
|
||||
|
||||
void Vmm::Virtio_gpu_control_request::_set_scanout()
|
||||
{
|
||||
Set_scanout scr { _desc_addr(0) };
|
||||
Control_header response { _desc_addr(1) };
|
||||
Set_scanout scr { _desc_range(0) };
|
||||
Control_header response { _desc_range(1) };
|
||||
|
||||
uint32_t id = scr.read<Set_scanout::Resource_id>();
|
||||
uint32_t sid = scr.read<Set_scanout::Scanout_id>();
|
||||
@ -177,8 +178,8 @@ void Vmm::Virtio_gpu_control_request::_set_scanout()
|
||||
|
||||
void Vmm::Virtio_gpu_control_request::_resource_flush()
|
||||
{
|
||||
Resource_flush rf { _desc_addr(0) };
|
||||
Control_header response { _desc_addr(1) };
|
||||
Resource_flush rf { _desc_range(0) };
|
||||
Control_header response { _desc_range(1) };
|
||||
|
||||
uint32_t id = rf.read<Resource_flush::Resource_id>();
|
||||
response.write<Control_header::Type>(Control_header::Type::ERR_INVALID_RESOURCE_ID);
|
||||
@ -229,8 +230,8 @@ void Vmm::Virtio_gpu_control_request::_resource_flush()
|
||||
|
||||
void Vmm::Virtio_gpu_control_request::_transfer_to_host_2d()
|
||||
{
|
||||
Transfer_to_host_2d tth { _desc_addr(0) };
|
||||
Control_header response { _desc_addr(1) };
|
||||
Transfer_to_host_2d tth { _desc_range(0) };
|
||||
Control_header response { _desc_range(1) };
|
||||
|
||||
uint32_t id = tth.read<Transfer_to_host_2d::Resource_id>();
|
||||
response.write<Control_header::Type>(Control_header::Type::ERR_INVALID_RESOURCE_ID);
|
||||
|
@ -56,11 +56,12 @@ class Vmm::Virtio_gpu_control_request
|
||||
using Descriptor = Virtio_gpu_queue::Descriptor;
|
||||
using Descriptor_array = Virtio_gpu_queue::Descriptor_array;
|
||||
|
||||
struct Control_header : Mmio
|
||||
template <size_t SIZE>
|
||||
struct Control_header_tpl : Mmio<SIZE>
|
||||
{
|
||||
enum { SIZE = 24 };
|
||||
using Base = Mmio<SIZE>;
|
||||
|
||||
struct Type : Register<0, 32>
|
||||
struct Type : Base::template Register<0, 32>
|
||||
{
|
||||
enum Commands {
|
||||
/* 2D commands */
|
||||
@ -95,17 +96,17 @@ class Vmm::Virtio_gpu_control_request
|
||||
ERR_INVALID_PARAMETER,
|
||||
};
|
||||
};
|
||||
struct Flags : Register<0x4, 32> {};
|
||||
struct Fence_id : Register<0x8, 64> {};
|
||||
struct Ctx_id : Register<0x10, 32> {};
|
||||
struct Flags : Base::template Register<0x4, 32> {};
|
||||
struct Fence_id : Base::template Register<0x8, 64> {};
|
||||
struct Ctx_id : Base::template Register<0x10, 32> {};
|
||||
|
||||
using Mmio::Mmio;
|
||||
using Base::Mmio;
|
||||
};
|
||||
|
||||
struct Display_info_response : Control_header
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 24*16 };
|
||||
using Control_header = Control_header_tpl<24>;
|
||||
|
||||
struct Display_info_response : Control_header_tpl<Control_header::SIZE + 24*16>
|
||||
{
|
||||
struct X : Register<0x18, 32> {};
|
||||
struct Y : Register<0x1c, 32> {};
|
||||
struct Width : Register<0x20, 32> {};
|
||||
@ -113,13 +114,11 @@ class Vmm::Virtio_gpu_control_request
|
||||
struct Enabled : Register<0x28, 32> {};
|
||||
struct Flags : Register<0x2c, 32> {};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
struct Resource_create_2d : Control_header
|
||||
struct Resource_create_2d : Control_header_tpl<Control_header::SIZE + 16>
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 16 };
|
||||
|
||||
struct Resource_id : Register<0x18, 32> {};
|
||||
|
||||
struct Format : Register<0x1c, 32>
|
||||
@ -139,42 +138,34 @@ class Vmm::Virtio_gpu_control_request
|
||||
struct Width : Register<0x20, 32> {};
|
||||
struct Height : Register<0x24, 32> {};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
struct Resource_unref : Control_header
|
||||
struct Resource_unref : Control_header_tpl<Control_header::SIZE + 8>
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 8 };
|
||||
|
||||
struct Resource_id : Register<0x18, 32> {};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
struct Resource_attach_backing : Control_header
|
||||
struct Resource_attach_backing : Control_header_tpl<Control_header::SIZE + 8>
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 8 };
|
||||
|
||||
struct Resource_id : Register<0x18, 32> {};
|
||||
struct Nr_entries : Register<0x1c, 32> {};
|
||||
|
||||
struct Memory_entry : Mmio
|
||||
struct Memory_entry : Mmio<16>
|
||||
{
|
||||
enum { SIZE = 16 };
|
||||
|
||||
struct Address : Register<0x0, 64> {};
|
||||
struct Length : Register<0x8, 32> {};
|
||||
|
||||
using Mmio::Mmio;
|
||||
};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
struct Set_scanout : Control_header
|
||||
struct Set_scanout : Control_header_tpl<Control_header::SIZE + 24>
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 24 };
|
||||
|
||||
struct X : Register<0x18, 32> {};
|
||||
struct Y : Register<0x1c, 32> {};
|
||||
struct Width : Register<0x20, 32> {};
|
||||
@ -182,26 +173,22 @@ class Vmm::Virtio_gpu_control_request
|
||||
struct Scanout_id : Register<0x28, 32> {};
|
||||
struct Resource_id : Register<0x2c, 32> {};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
struct Resource_flush : Control_header
|
||||
struct Resource_flush : Control_header_tpl<Control_header::SIZE + 24>
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 24 };
|
||||
|
||||
struct X : Register<0x18, 32> {};
|
||||
struct Y : Register<0x1c, 32> {};
|
||||
struct Width : Register<0x20, 32> {};
|
||||
struct Height : Register<0x24, 32> {};
|
||||
struct Resource_id : Register<0x28, 32> {};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
struct Transfer_to_host_2d :Control_header
|
||||
struct Transfer_to_host_2d :Control_header_tpl<Control_header::SIZE + 32>
|
||||
{
|
||||
enum { SIZE = Control_header::SIZE + 32 };
|
||||
|
||||
struct X : Register<0x18, 32> {};
|
||||
struct Y : Register<0x1c, 32> {};
|
||||
struct Width : Register<0x20, 32> {};
|
||||
@ -209,7 +196,7 @@ class Vmm::Virtio_gpu_control_request
|
||||
struct Offset : Register<0x28, 64> {};
|
||||
struct Resource_id : Register<0x30, 32> {};
|
||||
|
||||
using Control_header::Control_header;
|
||||
using Control_header_tpl::Control_header_tpl;
|
||||
};
|
||||
|
||||
Descriptor_array & _array;
|
||||
@ -232,14 +219,14 @@ class Vmm::Virtio_gpu_control_request
|
||||
return _array.get(idx);
|
||||
}
|
||||
|
||||
addr_t _desc_addr(unsigned i)
|
||||
Byte_range_ptr _desc_range(unsigned i)
|
||||
{
|
||||
Descriptor d = _desc(i);
|
||||
/* we only support 32-bit ram addresses by now */
|
||||
return _ram.local_address((addr_t)d.address(), d.length());
|
||||
return _ram.to_local_range({(char *)d.address(), d.length()});
|
||||
}
|
||||
|
||||
Control_header _ctrl_hdr { _desc_addr(0) };
|
||||
Control_header _ctrl_hdr { _desc_range(0) };
|
||||
|
||||
void _get_display_info();
|
||||
void _resource_create_2d();
|
||||
|
@ -67,10 +67,8 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
|
||||
Cpu::Signal_handler<Virtio_input_device> _handler;
|
||||
|
||||
struct Virtio_input_event : Mmio
|
||||
struct Virtio_input_event : Mmio<8>
|
||||
{
|
||||
enum { SIZE = 8 };
|
||||
|
||||
struct Type : Register<0, 16> {};
|
||||
struct Code : Register<2, 16> {};
|
||||
struct Value : Register<4, 32> {};
|
||||
@ -213,20 +211,20 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
if (!_queue[0].constructed())
|
||||
return;
|
||||
|
||||
bool irq = _queue[0]->notify([&] (addr_t addr, size_t size) {
|
||||
if (size < Virtio_input_event::SIZE) {
|
||||
warning("wrong virtioqueue packet size for input ", size);
|
||||
bool irq = _queue[0]->notify([&] (Byte_range_ptr const &data) {
|
||||
if (data.num_bytes < Virtio_input_event::SIZE) {
|
||||
warning("wrong virtioqueue packet size for input ", data.num_bytes);
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
Virtio_input_event vie(addr);
|
||||
Virtio_input_event vie(data);
|
||||
|
||||
if (_state == IN_MOTION) {
|
||||
vie.write<Virtio_input_event::Type>(Linux_evdev::EV_ABS);
|
||||
vie.write<Virtio_input_event::Code>(Linux_evdev::ABS_Y);
|
||||
vie.write<Virtio_input_event::Value>(_motion_y);
|
||||
_state = SYNC;
|
||||
return size;
|
||||
return data.num_bytes;
|
||||
}
|
||||
|
||||
if (_state == SYNC) {
|
||||
@ -234,7 +232,7 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
vie.write<Virtio_input_event::Code>(0);
|
||||
vie.write<Virtio_input_event::Value>(0);
|
||||
_state = READY;
|
||||
return size;
|
||||
return data.num_bytes;
|
||||
}
|
||||
|
||||
if (_num_events == _idx_events) {
|
||||
@ -269,7 +267,7 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
_motion_y = y;
|
||||
_state = IN_MOTION;
|
||||
});
|
||||
return size;
|
||||
return data.num_bytes;
|
||||
});
|
||||
|
||||
if (irq) _buffer_notification();
|
||||
|
@ -51,21 +51,21 @@ class Vmm::Virtio_net : public Virtio_device<Virtio_split_queue, 2>
|
||||
void _rx()
|
||||
{
|
||||
/* RX */
|
||||
auto recv = [&] (addr_t data, size_t size)
|
||||
auto recv = [&] (Byte_range_ptr const &data)
|
||||
{
|
||||
if (!_nic.rx()->packet_avail() || !_nic.rx()->ready_to_ack())
|
||||
return 0ul;
|
||||
|
||||
Nic::Packet_descriptor const rx_packet = _nic.rx()->get_packet();
|
||||
|
||||
size_t sz = Genode::min(size, rx_packet.size() + NIC_HEADER_SIZE);
|
||||
size_t sz = Genode::min(data.num_bytes, rx_packet.size() + NIC_HEADER_SIZE);
|
||||
|
||||
Genode::memcpy((void *)(data + NIC_HEADER_SIZE),
|
||||
Genode::memcpy((void *)(data.start + NIC_HEADER_SIZE),
|
||||
_nic.rx()->packet_content(rx_packet),
|
||||
sz - NIC_HEADER_SIZE);
|
||||
_nic.rx()->acknowledge_packet(rx_packet);
|
||||
|
||||
Genode::memset((void*)data, 0, NIC_HEADER_SIZE);
|
||||
Genode::memset((void*)data.start, 0, NIC_HEADER_SIZE);
|
||||
|
||||
return sz;
|
||||
};
|
||||
@ -79,22 +79,22 @@ class Vmm::Virtio_net : public Virtio_device<Virtio_split_queue, 2>
|
||||
|
||||
void _tx()
|
||||
{
|
||||
auto send = [&] (addr_t data, size_t size)
|
||||
auto send = [&] (Byte_range_ptr const &data)
|
||||
{
|
||||
if (!_nic.tx()->ready_to_submit()) return 0lu;
|
||||
|
||||
data += NIC_HEADER_SIZE; size -= NIC_HEADER_SIZE;
|
||||
Byte_range_ptr body {data.start + NIC_HEADER_SIZE, data.num_bytes - NIC_HEADER_SIZE};
|
||||
|
||||
Nic::Packet_descriptor tx_packet;
|
||||
try {
|
||||
tx_packet = _nic.tx()->alloc_packet(size); }
|
||||
tx_packet = _nic.tx()->alloc_packet(body.num_bytes); }
|
||||
catch (Nic::Session::Tx::Source::Packet_alloc_failed) {
|
||||
return 0ul; }
|
||||
|
||||
Genode::memcpy(_nic.tx()->packet_content(tx_packet),
|
||||
(void *)data, size);
|
||||
(void *)body.start, body.num_bytes);
|
||||
_nic.tx()->submit_packet(tx_packet);
|
||||
return size;
|
||||
return body.num_bytes;
|
||||
};
|
||||
|
||||
if (!_queue[TX].constructed()) return;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user