\input{configpres}

\title{Driver Module Basics}
\maketitle

\subsection{Kernel Module}

\begin{frame}[fragile]
\frametitle{Driver Module Structure}
\begin{itemize}
\item Header
\begin{scriptsize}
\begin{lstlisting}[frame=trBL]
#include <linux/init.h>
#include <linux/module.h>
\end{lstlisting}
\end{scriptsize}
\pause
\item Init
\begin{scriptsize}
\begin{lstlisting}[frame=trBL]
static int __init vain_init(void)
{
        printk(KERN_INFO "vain_init: done\n");
        return 0;
}

module_init(vain_init);
\end{lstlisting}
\end{scriptsize}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Driver Module Structure}
\begin{itemize}
\item Exit
\begin{scriptsize}
\begin{lstlisting}[frame=trBL]
static void __exit vain_exit(void)
{
        printk(KERN_INFO "vain_exit: done\n");
}

module_exit(vain_exit);
\end{lstlisting}
\end{scriptsize}
\pause
\item Description
\begin{tiny}
\begin{lstlisting}[frame=trBL]
MODULE_AUTHOR("Benedikt Spranger <b.spranger@linutronix.de>");
MODULE_DESCRIPTION("a more or less useless module");
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0815");
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain/vain.c}
\end{tiny}
\end{frame}

\subsubsection{Kernel Build System}
\begin{frame}[fragile]
\frametitle{Kconfig}
drivers/staging/Kconfig:
\begin{scriptsize}
\begin{lstlisting}
..
source "drivers/staging/vain/Kconfig"
..
\end{lstlisting}
\end{scriptsize}
drivers/staging/vain/Kconfig:
\begin{scriptsize}
\begin{lstlisting}
config VAIN
       tristate "vain test driver"
       ---help---
         Say Y here if you want the VAIN Test Driver in your kernel.
\end{lstlisting}
\end{scriptsize}
results in CONFIG\_VAIN = ['y'|'n'|'m']
\end{frame}
\begin{frame}[fragile]
\frametitle{Makefile}
drivers/staging/Makefile:
\begin{scriptsize}
\begin{lstlisting}
..
obj-$(CONFIG_VAIN) += vain/
..
\end{lstlisting}
\end{scriptsize}
drivers/staging/vain/Makefile:
\begin{scriptsize}
\begin{lstlisting}
obj-$(CONFIG_VAIN) += vain.o
\end{lstlisting}
\end{scriptsize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Build, Load, and Unload the Module}
\begin{itemize}
\item Build
\begin{tiny}
\begin{verbatim}
$ make menuconfig
\end{verbatim}
and select Drivers / Staging / vain test driver with 'm' to be built as a
module.
\begin{verbatim}
...
  CC [M]  vain.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      vain.mod.o
  LD [M]  vain.ko
...
\end{verbatim}
\end{tiny}
\pause
\item Load
\begin{tiny}
\begin{verbatim}
# insmod drivers/staging/vain/vain.ko
vain_init: done
#
\end{verbatim}
\end{tiny}
\pause
\item Unload
\begin{tiny}
\begin{verbatim}
# rmmod vain
vain_exit: done
#
\end{verbatim}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{More Complex Modules}
\pause
\begin{itemize}
\item Member of a Bus
\begin{itemize}
\item PCI
\item Platform
\item USB
\item \dots
\pause
\end{itemize}
\item Part of a Subsystem\footnote{not presented here}
\begin{itemize}
\item Character Devices
\item Block Devices
\item Network Devices
\item \dots
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Module Structure}
\pause
\begin{itemize}
\item Header
\begin{tiny}
\begin{lstlisting}[frame=trBL]
#include <linux/init.h>
#include <linux/module.h>
|#include <linux/pci.h>|
\end{lstlisting}
\end{tiny}
\pause
\item Init
\begin{tiny}
\begin{lstlisting}[frame=trBL]
static int __init vain_pci_init(void)
{
        int err;

        |err = pci_register_driver(&vain_pci_driver);|

        if (!err)
                printk(KERN_INFO "vain_pci_init: done\n");
        return err;
}

module_init(vain_pci_init);
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Module Structure}
\begin{itemize}
\item Exit
\begin{tiny}
\begin{lstlisting}[frame=trBL]
static void __exit vain_pci_exit(void)
{
        |pci_unregister_driver(&vain_pci_driver);|
        printk(KERN_INFO ``vain_pci_exit: done\n'');
}

module_exit(vain_pci_exit);
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Module Structure}
\begin{itemize}
\item struct pci\_driver
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static struct pci_driver vain_pci_driver = {
        .name =         "vain_pci",
        .id_table =     vain_pci_ids,
        .probe =        vain_pci_probe,
        .remove =       vain_pci_remove,
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Module Structure}
\begin{itemize}
\item struct struct pci\_device\_id
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static struct pci_device_id vain_pci_ids[] = {
        {PCI_VENDOR_ID_ILLEGAL_VENDOR,
         PCI_DEVICE_ID_ILLEGAL_VENDOR_DEVICE,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        { /* end of table */ }
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Module Structure}
\begin{itemize}
\item probe
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static int vain_pci_probe(struct pci_dev *pdev,
                           const struct pci_device_id *ent)
{
        struct vain_pci_info *info;
        int ret;

        info = kzalloc(sizeof(struct vain_pci_info), GFP_KERNEL);

        info->pdev = pdev;

        ret = pci_enable_device(pdev);

        ret = pci_request_regions(pdev, "vain_pci");

        info->base = pci_ioremap_bar(pdev, 0);

        pci_set_drvdata(pdev, info);

        return 0;|
\end{lstlisting}
\dots
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Module Structure}
\begin{itemize}
\item remove
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static void vain_pci_remove(struct pci_dev *pdev)
{
        struct vain_pci_info *info = pci_get_drvdata(pdev);

        iounmap(info->base);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);

        kfree (info);
}|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{PCI Driver Module Loading / Unloading}
\includegraphics[width=7cm]{images/PCI_driver.png}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_pci/vain_pci_1.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_pci/vain_pci_2.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_pci/vain_pci_3.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_pci/vain_pci_4.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_pci/vain_pci_5.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{PCI Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_pci/vain_pci_6.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Module Structure}
\pause
\begin{itemize}
\item Header
\begin{tiny}
\begin{lstlisting}[frame=trBL]
#include <linux/init.h>
#include <linux/module.h>
|#include <linux/platform_device.h>|
\end{lstlisting}
\end{tiny}
\pause
\item Init
\begin{tiny}
\begin{lstlisting}[frame=trBL]
static int __init vain_plat_init(void)
{
        int err;

        |err = platform_driver_register(&vain_plat_driver);|

        if (!err)
                printk(KERN_INFO ``vain_plat_init: done\n'');
        return err;
}
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Module Structure}
\begin{itemize}
\item Exit
\begin{tiny}
\begin{lstlisting}[frame=trBL]
static void __exit vain_plat_exit(void)
{
        |platform_driver_unregister(&vain_plat_driver);|
        printk(KERN_INFO ``vain_plat_exit: done\n'');
}
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Module Structure}
\begin{itemize}
\item struct platform\_driver
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static struct platform_driver vain_plat_driver = {
        .driver         = {
                .name   = "vain_plat",
                .owner  = THIS_MODULE,
                .of_match_table = vain_match,
        },
        .probe          = vain_plat_probe,
        .remove         = vain_plat_remove,
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Module Structure}
\begin{itemize}
\item struct of\_device\_id
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static const struct of_device_id vain_match[] = {
        { .compatible = "example,vain", },
        { /* end of table */ }
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Module Structure}
\begin{itemize}
\item probe
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static int vain_plat_probe(struct platform_device *pdev)
{
        struct vain_plat_info *info;
        struct resource *res, *mem;
        int err;

        info = kzalloc(sizeof(struct vain_plat_info), GFP_KERNEL);

        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

        mem = request_mem_region(res->start, resource_size(res),
                                 pdev->name);

        info->base = ioremap(res->start, resource_size(res));

        platform_set_drvdata(pdev, info);

        return 0;|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Module Structure}
\begin{itemize}
\item remove
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static int vain_plat_remove(struct platform_device *pdev)
{
        struct vain_plat_info *info = platform_get_drvdata(pdev);
        struct resource *res;

        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        iounmap(info->base);
        release_mem_region(res->start, resource_size(res));
        platform_set_drvdata(pdev, NULL);

        kfree (info);

        return 0;
}|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{Platform Driver Module Loading / Unloading}
\includegraphics[width=7cm]{images/plat_driver.png}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_plat/vain_plat_1.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_plat/vain_plat_2.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_plat/vain_plat_3.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_plat/vain_plat_4.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_plat/vain_plat_5.c}
\end{tiny}
\end{frame}

\begin{frame}[fragile]
\frametitle{Platform Driver Skeleton}
\begin{tiny}
\lstinputlisting{kernel-devel/module-basics/vain_plat/vain_plat_6.c}
\end{tiny}
\end{frame}

\input{tailpres}
