1,7 → 1,79 |
<?xml version="1.0" encoding="UTF-8"?> |
<chapter id="hardware"> |
<?dbhtml filename="hardware.html"?> |
|
<chapter id="hardware"><?dbhtml filename="hardware.html"?> |
<title>Hardware handling. Device drivers.</title> |
<title>Device drivers</title> |
|
<para></para> |
</chapter> |
<para>Since HelenOS is a microkernel, a framework for supporting userspace |
device drivers has been implemented. A typical userspace task acting as a |
device driver might need to: </para> |
|
<itemizedlist> |
<listitem> |
<para>receive notifications about interrupts sent by its device,</para> |
</listitem> |
|
<listitem> |
<para>access physical memory address space,</para> |
</listitem> |
|
<listitem> |
<para>access I/O space and</para> |
</listitem> |
|
<listitem> |
<para>control preemption.</para> |
</listitem> |
</itemizedlist> |
|
<section> |
<title>Interrupt notifications</title> |
|
<para>Userspace tasks that are in hold of the |
<constant>CAP_IRQ_REG</constant> capability can register themselves via |
the <code>ipc_register_irq()</code> to be notified about occurrences of a |
given interrupt. The registration call takes two arguments. The first |
argument is the IRQ number and the second is the pointer to special |
pseudocode that instructs the kernel interrupt handler how to process the |
IRQ. Currently the pseudocode language supports reading and writing |
physical memory, reading from and writing to I/O space and actions related |
to running HelenOS in virtual environments.</para> |
|
<para>When the interrupt comes after its handler has been registered by a |
userspace task, the kernel interrupt handler interprets the pseudocode |
program and sends an IPC notification to the respective task. The |
userspace task can get certain information about the interrupt (e.g. what |
key was pressed) by issuing memory or I/O space reads in the pseudocode |
program. The read values are wrapped into the IPC notification sent to the |
task. The write operations are also very essential because some interrupts |
are level-sensitive and need to be processed in the kernel interrupt |
routine. In many situations, the interrupt is considered serviced only |
when the interrupt handler performs certain reads or writes of memory or |
I/O space.</para> |
</section> |
|
<section> |
<title>Accessing memory and I/O space</title> |
|
<para>When a task has the <constant>CAP_MEM_MANAGER</constant> capability, |
it can use the <constant>SYS_MAP_PHYSMEM</constant> to map regions of |
physical memory to its address space. When successful, the syscall creates |
an address space area for the physical memory region. The address space |
area can be further shared by other tasks. Similarily, when a task has the |
<constant>CAP_IOSPACE_MANAGER</constant> capability, it is entitled to |
request access to the I/O space by using the |
<constant>SYS_IOSPACE_ENABLE</constant>. However, this syscall is relevant |
only on architectures that have separate I/O space (e.g. amd64 and |
ia32).</para> |
</section> |
|
<section> |
<title>Disabling preemption</title> |
|
<para>It might be desirable for a device driver to temporarily disable |
preemption. Tasks that can do this are required to have the |
CAP_PREEMPT_CONTROL capability. Preemption could be theoretically disabled |
by disabling interrupts on the current processor, but disabling preemption |
is more lightweight as interrupt processing remains enabled.</para> |
</section> |
</chapter> |