\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 #include \end{lstlisting} \end{scriptsize} \pause \item Init \begin{scriptsize} \begin{lstlisting}[frame=trBL] static int 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 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 "); 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{Makefile} \begin{frame}[fragile] \frametitle{Makefile} \begin{scriptsize} \lstinputlisting[language=make]{kernel-devel/module-basics/vain/Makefile} \end{scriptsize} \end{frame} \begin{frame}[fragile] \frametitle{Build, Load, and Unload the Module} \begin{itemize} \item Build \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 Load \begin{tiny} \begin{verbatim} # insmod ./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 #include |#include | \end{lstlisting} \end{tiny} \pause \item Init \begin{tiny} \begin{lstlisting}[frame=trBL] static int 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 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 #include |#include | \end{lstlisting} \end{tiny} \pause \item Init \begin{tiny} \begin{lstlisting}[frame=trBL] static int 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 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}