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