\documentclass{beamer}
\usetheme{linutronix}
\usepackage{german}
\usepackage[utf8]{inputenc}
\usepackage{pgf}
\usepackage{graphicx}
\usepackage{psfrag}
\usepackage{listings}

\title{Treiber Modul Grundlagen}
\institute{Linutronix GmbH}

\begin{document}
\lstset{language=[ANSI]C, moredelim=[is][\color{blue}]{|}{|}}
\maketitle

% ----- Slide Aufbau ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines Treiber Moduls}
\pause
\begin{itemize}
\item Header
\pause
\begin{scriptsize}
\begin{lstlisting}[frame=trBL]
#include <linux/init.h>
#include <linux/module.h>
\end{lstlisting}
\end{scriptsize}
\pause
\item Init
\pause
\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}

% ----- Slide Aufbau (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Aufbau (fort.)}
\begin{itemize}
\item Exit
\pause
\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 Beschreibung
\pause
\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}

% ----- Slide Rumpf Treiber ------------------
\begin{frame}[fragile]
\frametitle{Rumpf Treiber}
\begin{tiny}
\lstinputlisting{vain/vain.c}
\end{tiny}
\end{frame}

% ----- Slide Makefile ------------------
\begin{frame}[fragile]
\frametitle{Makefile}
\begin{scriptsize}
\lstinputlisting[language=make]{vain/Makefile}
\end{scriptsize}
\end{frame}

% ----- Slide build ------------------
\begin{frame}[fragile]
\frametitle{Bauen, laden und entladen des Moduls}
\begin{itemize}
\item Bauen
\pause
\begin{tiny}
\begin{verbatim}
$ make
make -C /lib/modules/2.6.30/build M=/path/to/vain modules
make[1]: Entering directory `/usr/src/linux-2.6.30'
  CC [M]  /path/to/vain/vain.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /path/to/vain/vain.mod.o
  LD [M]  /path/to/vain/vain.ko
make[1]: Leaving directory `/usr/src/linux-2.6.30'
$
\end{verbatim}
\end{tiny}
\pause
\item Laden
\pause
\begin{tiny}
\begin{verbatim}
# insmod ./vain.ko
vain_init: done
#
\end{verbatim}
\end{tiny}
\item Entladen
\pause
\begin{tiny}
\begin{verbatim}
# rmmod vain
vain_exit: done
#
\end{verbatim}
\end{tiny}
\end{itemize}
\end{frame}

% ----- Slide Komplexere Module ------------------
\begin{frame}
\frametitle{Komplexere Module}
\pause
\begin{itemize}
\item Teil eines Bussystems
\pause
\begin{itemize}
\item PCI
\pause
\item Platform
\pause
\item USB
\pause
\item \dots
\pause
\end{itemize}
\item Teil eines Subsystems\footnote{nicht Teil des Vortrages}
\pause
\begin{itemize}
\item Character-Devices
\pause
\item Block-Devices
\pause
\item Network-Devices
\pause
\item \dots
\end{itemize}
\end{itemize}
\end{frame}

% ----- Slide PCI Treiber ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines PCI Treiber Moduls}
\pause
\begin{itemize}
\item Header
\pause
\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
\pause
\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}

% ----- Slide PCI Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines PCI Treiber Moduls (fort.)}
\begin{itemize}
\item Exit
\pause
\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}

% ----- Slide PCI Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines PCI Treiber Moduls (fort.)}
\begin{itemize}
\item struct pci\_driver
\pause
\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 =       __devexit_p(vain_pci_remove),
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

% ----- Slide PCI Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines PCI Treiber Moduls (fort.)}
\begin{itemize}
\item struct struct pci\_device\_id
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static struct pci_device_id vain_pci_ids[] __devinitdata = {
        {PCI_VENDOR_ID_ILLEGAL_VENDOR, PCI_DEVICE_ID_ILLEGAL_VENDOR_DEVICE,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        {0, }
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

% ----- Slide PCI Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines PCI Treiber Moduls (fort.)}
\begin{itemize}
\item probe
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static int __devinit vain_pci_probe(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
{
        int ret;

        ret = pci_enable_device(pdev);
        if (ret)
        	goto err_free;

        ret = pci_request_regions(pdev, "vain_pci");
        if (ret)
                goto err_disable_device;

        info->base = pci_ioremap_bar(pdev, 0);
        if (!info->base) {
                ret = -ENODEV;
                goto err_rel_regs;
        }

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

% ----- Slide PCI Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines PCI Treiber Moduls (fort.)}
\begin{itemize}
\item remove
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static void __devexit 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}

% ----- Slide PCI Treiber Hintergrund ------------------
\begin{frame}
\frametitle{PCI Treiber Hintergrund}
\includegraphics[width=7cm]{images/PCI_driver.png}
\end{frame}

% ----- Slide PCI Rumpf Treiber ------------------
\begin{frame}[fragile]
\frametitle{PCI Rumpf Treiber}
\begin{tiny}
\lstinputlisting{vain_pci/vain_pci_1.c}
\end{tiny}
\end{frame}

% ----- Slide PCI Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{PCI Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_pci/vain_pci_2.c}
\end{tiny}
\end{frame}

% ----- Slide PCI Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{PCI Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_pci/vain_pci_3.c}
\end{tiny}
\end{frame}

% ----- Slide PCI Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{PCI Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_pci/vain_pci_4.c}
\end{tiny}
\end{frame}

% ----- Slide PCI Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{PCI Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_pci/vain_pci_5.c}
\end{tiny}
\end{frame}

% ----- Slide PCI Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{PCI Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_pci/vain_pci_6.c}
\end{tiny}
\end{frame}

% ----- Slide Platform Treiber ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines Platform Treiber Moduls}
\pause
\begin{itemize}
\item Header
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
#include <linux/init.h>
#include <linux/module.h>
|#include <linux/platform_device.h>

#include <asm/io.h>|
\end{lstlisting}
\end{tiny}
\pause
\item Init
\pause
\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}

% ----- Slide Platform Treiber ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines Platform Treiber Moduls (fort.)}
\pause
\begin{itemize}
\item Exit
\pause
\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}

% ----- Slide Platform Treiber ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines Platform Treiber Moduls (fort.)}
\pause
\begin{itemize}
\item struct platform\_driver
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static struct platform_driver vain_plat_driver = {
        .driver         = {
                .name   = "vain_plat",
                .owner  = THIS_MODULE,
        },
        .probe          = vain_plat_probe,
        .remove         = __devexit_p(vain_plat_remove),
};|
\end{lstlisting}
\end{tiny}
\end{itemize}
\end{frame}

% ----- Slide Platform Treiber ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines Platform Treiber Moduls (fort.)}
\pause
\begin{itemize}
\item probe
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static int __devinit vain_plat_probe(struct platform_device *pdev)
{
        struct resource *res;
        int err;

        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!res))
                goto err_free;

        mem = request_mem_region(res->start, resource_size(res), pdev->name);
        if (!mem)
                goto err_free;

        info->base = ioremap(res->start, resource_size(res));
        if (!info->base)
                goto err_ioremap;

        platform_set_drvdata(pdev, info);

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

% ----- Slide Platform Treiber ------------------
\begin{frame}[fragile]
\frametitle{Aufbau eines Platform Treiber Moduls (fort.)}
\pause
\begin{itemize}
\item remove
\pause
\begin{tiny}
\begin{lstlisting}[frame=trBL]
|static int __devexit 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}

% ----- Slide PCI Treiber Hintergrund ------------------
\begin{frame}
\frametitle{Platform Treiber Hintergrund}
\includegraphics[width=7cm]{images/plat_driver.png}
\end{frame}

% ----- Slide Platform Rumpf Treiber ------------------
\begin{frame}[fragile]
\frametitle{Platform Rumpf Treiber}
\begin{tiny}
\lstinputlisting{vain_plat/vain_plat_1.c}
\end{tiny}
\end{frame}

% ----- Slide Platform Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Platform Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_plat/vain_plat_2.c}
\end{tiny}
\end{frame}

% ----- Slide Platform Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Platform Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_plat/vain_plat_3.c}
\end{tiny}
\end{frame}

% ----- Slide Platform Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Platform Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_plat/vain_plat_4.c}
\end{tiny}
\end{frame}

% ----- Slide Platform Rumpf Treiber (fort.) ------------------
\begin{frame}[fragile]
\frametitle{Platform Rumpf Treiber (fort.)}
\begin{tiny}
\lstinputlisting{vain_plat/vain_plat_5.c}
\end{tiny}
\end{frame}

\end{document}
