70 lines
3.2 KiB
TeX
70 lines
3.2 KiB
TeX
\label{chap:ahcid}
|
|
|
|
\section{Introduction}
|
|
|
|
\subsection{Public IDC Interface}
|
|
|
|
ahcid's design is modeled after netd. It has a small \acs{idc} interface that
|
|
facilitates user access to a port: when registering for a port, the user is
|
|
given the capability for the port registers. Interrupts are forwarded via
|
|
\acs{idc} messages. Currently the interface also provides access to the {\tt
|
|
IDENTIFY} data of all available disks. This is useful to determine the type of
|
|
device and total disk space without having to open the port.
|
|
|
|
\begin{center}
|
|
\begin{minipage}{100mm}
|
|
\begin{lstlisting}[label={code:ahci_mgmt.if}, caption={ahci management Flounder
|
|
interface}]
|
|
interface ahci_mgmt "AHCI Management Daemon" {
|
|
|
|
rpc list(out uint8 port_ids[len]);
|
|
rpc identify(in uint8 port_id,
|
|
out uint8 identify_data[data_len]);
|
|
|
|
rpc open(in uint8 port_id, out errval status,
|
|
out cap controller_mem, out
|
|
uint64 offset, out uint32 capabilities);
|
|
rpc close(in uint8 port_id, out errval status);
|
|
|
|
message command_completed(uint8 port_id,
|
|
uint32 interrupt_status);
|
|
};
|
|
\end{lstlisting}
|
|
\end{minipage}
|
|
\end{center}
|
|
|
|
\section{Initialization}
|
|
|
|
ahcid registers itself as a driver for the \ac{ahci} device class. Once the
|
|
init procedure is called, ahcid consults the received base address registers to
|
|
find the memory region used for the \acs{hba}'s registers.
|
|
|
|
As a first step, the \ac{hba} is reset in order to get to a known state. The
|
|
\ac{hba} is also put into \ac{ahci} mode. After the initial reset, ahcid
|
|
discovers the number of ports and detects which of them are implemented and
|
|
have a disk connected. Discovered disks are assigned a system-wide unique port
|
|
id and are registered with the skb. For every disk, an \ac{ata} {\tt IDENTIFY}
|
|
command is sent to determine the disk's parameters. A copy of the {\tt
|
|
IDENTIFY} response is cached in ahcid for later use.
|
|
|
|
After all attached disks are initialized, ahcid exports the ahci management
|
|
interface, which clients can then use to register themselves for a single port.
|
|
|
|
\section{Interrupt Handling}
|
|
|
|
ahcid registers itself as an interrupt handler for the \ac{ahci} \ac{hba}
|
|
controller when calling \lstinline+pci_register_driver_irq+. The interrupt
|
|
handler extracts the current interrupt state of the controller from the device
|
|
memory and decides if the interrupt was triggered by the \ac{hba}. If the
|
|
interrupt was triggered by the \ac{hba}, the handler loops over all ports and
|
|
checks which ports received an interrupt and clears the port's interrupt
|
|
register. The \ac{hba}'s interrupt register is cleared after all port interrupt
|
|
registers have been cleared. At last, if a client is registered for a port that
|
|
has received an interrupt, ahcid sends a \lstinline+command_completed+ message
|
|
(\autoref{code:ahci_mgmt.if}) using the established \lstinline+ahci_mgmt+
|
|
interface. Clearing the interrupts before delivering the completion messages to
|
|
the respective users ensures that we do not miss interrupts that would be
|
|
triggered as a consequence of any commands issued in the command completion
|
|
handler. Missing any interrupts for further completions could deadlock a user
|
|
since we do not poll the port's state if no interrupts have been triggered.
|