\documentclass[addpoints,12pt]{exam}

\usepackage{ngerman}
\usepackage{listings,color}
\usepackage{graphicx}

\firstpageheadrule
\runningheadrule
\lhead{Manuel Traut\\Sommersemester 2017}
\chead{Hochschule Ravensburg-Weingarten\\Linux-Kernelprogrammierung}
\rhead{MatrNr:\\Datum:}

\firstpagefootrule
\runningfootrule
\firstpagefooter{Page \thepage\ of \numpages}
{}
{Punkte: \makebox[.5in]{\hrulefill}\\
von \pointsonpage{\thepage} Punkten}

\runningfooter{Page \thepage\ of \numpages}
{}
{}

\pagestyle{headandfoot}

\pointsinrightmargin
\pointpoints{Punkt}{Punkte}

\begin{document}


\begin{coverpages}
\begin{titlepage}
\title{Pr\"ufung Linux-Kernelprogrammierung}
\author{Dozent: Manuel Traut}
\date{12. Juli 2017 08:00 Uhr}
\maketitle
\begin{center}
Hochschule Ravensburg-Weingarten
\vspace{1cm}

Dauer: 60 Minuten, erlaubte Hilfsmittel: eigene Mitschriebe/Notizen
\end{center}

\vspace{2cm}
Name:\enspace\hrulefill
\vspace{2cm}
MatrNr:\enspace\hrulefill
\begin{center}
\begin{lstlisting}
              a8888b.
             d888888b.
             8P"YP"Y88      (((((((())))))))))
             8|o||o|88      ||VIEL ERFOLG !!||
             8'    .88      ((((((((((((()))))
             8`._.' Y8.
            d/      `8b.
          .dP   .     Y8b.
         d8:'   "   `::88b.
        d8"           `Y88b
       :8P     '       :888
        8a.    :      _a88P
      ._/"Yaa_ :    .| 88P|
      \    YP"      `| 8P  `.
      /     \._____.d|    .'
      `--..__)888888P`._.'
\end{lstlisting}
\end{center}
\end{titlepage}
\end{coverpages}

\lstset{ %
  basicstyle=\scriptsize,   % the size of the fonts that are used for the code
  breaklines=true,          % sets automatic line breaking
  frame=single,             % adds a frame around the code
  language=C,               % the language of the code
  numbers=left,             % where to put the line-numbers;
  numbersep=5pt,            % how far the line-numbers are from the code
  numberstyle=\tiny,        % the style that is used for the line-numbers
  tabsize=8,                % sets default tabsize to 2 spaces
}


\begin{questions}

\question Sie haben einen Roboter entwickelt. Zur Steuerung des Roboters wurde
  ein ARM basiertes Linuxsystem integriert. Um die Sensoren und Aktoren des
  Roboters vom User-space zugreifbar zu machen haben Sie den Linuxkernel
  modifiziert. Die Steuerungsapplikation l\"auft im Userspace und wurde nur
  gegen die unter LGPL stehende glibc gelinkt.

\begin{parts}
\part[2] Argumentieren Sie weshalb es f\"ur zuk\"unftige Entwicklungen am
  Roboter f\"ur Ihre Firma von Vorteil ist, die \"Anderungen am Kernel
  Mainline zu bekommen.

\part[4] Sie wollen Ihre Modifikationen am Kernel in Mainline Linux
  integriert haben. Was \"ubermitteln Sie auf welchem Weg wohin?

\part[4] Welche Aufgaben haben die Kernel Maintainer in diesem Zusammenhang?

\part[1] M\"ussen Sie die K\"aufer des Roboters informieren, dass Sie Linux
  einsetzen?

\part[1] Wem m\"ussen Sie auf Anfrage die Modifikationen am Kernel zur
  Verf\"ugung stellen?

\part[1] Wem m\"ussen Sie auf Anfrage den Quellcode Ihrer Applikation zur
  Verf\"ugung stellen?
\end{parts}

\question
\begin{parts}
\part[2] Welches Kommando f\"uhrt zu den Ausgaben auf folgendem Bild?
\part[2] \"Uber welche Dateien wird der Inhalt / Struktur des Tools gesteuert?
\part[2] Der Kernel kann 'out of tree' gebaut werden. Nenne 2 Vorteile dieser
	Methode.
\end{parts}
\includegraphics[width=0.8\textwidth]{./menuconfig.png}

\question
\begin{parts}
\part[6]Beschreiben Sie den Releasezyklus des Linuxkernels. Erkl\"aren Sie in
diesem Zusammenhang auch die Begriffe 'Release Candidate', 'Release', 'stable
Kernel' und 'staging'.
\end{parts}

\question
\begin{parts}
\part[6]Das Linuxtreibermodell kennt verschiedene Treiberarten. Worin
unterscheidet sich der Code zur Registrierung eines 'usb\_device\_driver' von
einem 'pci\_device\_driver'?
\end{parts}

\question
\begin{parts}
\part[6]Was wissen Sie über die Tracing Infrastruktur (ftrace) im Linux Kernel?
	(Nennen Sie 3 Punkte)
\end{parts}

\newpage

\question
Die folgenden Fragen beziehen sich auf den Quellcode 1 im Anhang.
\begin{parts}
\part[2] Der Treiber wird in einem System geladen, welches 2 PCI Devices mit
	Vendor ID 0x186c und Device ID 0x0624 besitzt. Wie oft wird mf624\_pci\_probe
	und mf624\_init aufgerufen?
\part[4] Egal auf welches Device Sie zugreifen, Sie interagieren immer nur mit
	einer der zwei PCI Karten. Wie m\"usssen Sie den Treiber modifizieren, damit
	beide Karten funktionieren?
\part[2] Sie wollen dass der Code nicht mehr angesprungen wird, welche Zeile(n)
	m\"ussen Sie mindestens l\"oschen?
\end{parts}

\question
Die folgenden Fragen beziehen sich auf den Quellcode 2 im Anhang.
\begin{parts}
\part[10] Mit den Funktionen 'set\_latch\_green und get\_latch\_green' (welche
in asm/mach-rc32434/gpio.h definiert sind) kann analog zu den bereits verwendeten
Funktionen 'set\_latch\_u5 / get\_latch\_u5' eine gr\"une LED angesteuert
werden. Erweitern Sie den Treiber so, dass die gr\"une LED z.B. mit
	'echo 1 > /sys/class/leds/huhu/brightness'
eingeschaltet werden kann.
\end{parts}

\end{questions}

\vspace{1cm}
Punkte: \_\_\_\_ von \numpoints
\hspace{1cm}
Note:

\newpage

\begin{appendix}

Quellcode 1:

\begin{lstlisting}
/*
 * UIO driver fo Humusoft MF624 DAQ card.
 * Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com>,
 *                    Czech Technical University in Prague
 *
 * Copyright (C) 2016 Manuel Traut <manut@mecka.net>,
 *                    modified for usage in kernel exams
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/uio_driver.h>

#define PCI_VENDOR_ID_HUMUSOFT		0x186c
#define PCI_DEVICE_ID_MF624		0x0624

/* BAR0 Interrupt control/status register */
#define INTCSR				0x4C
#define INTCSR_ADINT_ENABLE		(1 << 0)
#define INTCSR_CTR4INT_ENABLE		(1 << 3)
#define INTCSR_PCIINT_ENABLE		(1 << 6)
#define INTCSR_ADINT_STATUS		(1 << 2)
#define INTCSR_CTR4INT_STATUS		(1 << 5)

enum mf624_interrupt_source {ADC, CTR4, ALL};

static void mf624_disable_interrupt(enum mf624_interrupt_source source,
			     struct uio_info *info)
{
	void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;

	switch (source) {
	case ADC:
		iowrite32(ioread32(INTCSR_reg)
			& ~(INTCSR_ADINT_ENABLE | INTCSR_PCIINT_ENABLE),
			INTCSR_reg);
		break;
	case CTR4:
	default:
		iowrite32(ioread32(INTCSR_reg)
			& ~(INTCSR_CTR4INT_ENABLE | INTCSR_PCIINT_ENABLE),
			INTCSR_reg);
		break;
	}
}

static irqreturn_t mf624_irq_handler(int irq, struct uio_info *info)
{
	void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;

	if ((ioread32(INTCSR_reg) & INTCSR_ADINT_ENABLE)
	    && (ioread32(INTCSR_reg) & INTCSR_ADINT_STATUS)) {
		mf624_disable_interrupt(ADC, info);
		return IRQ_HANDLED;
	}

	if ((ioread32(INTCSR_reg) & INTCSR_CTR4INT_ENABLE)
	    && (ioread32(INTCSR_reg) & INTCSR_CTR4INT_STATUS)) {
		mf624_disable_interrupt(CTR4, info);
		return IRQ_HANDLED;
	}
	return IRQ_NONE;
}

static struct uio_info mf624_info = {
	.name = "mf624";
	.version = "0.0.1";
};

static int mf624_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
	struct uio_info *info = &mf624_info;

	if (pci_enable_device(dev))
		return -1;

	if (pci_request_regions(dev, "mf624"))
		goto out_disable;

	/* BAR0 */
	info->mem[0].name = "PCI chipset, interrupts, status "
			"bits, special functions";
	info->mem[0].addr = pci_resource_start(dev, 0);
	if (!info->mem[0].addr)
		goto out_release;
	info->mem[0].size = pci_resource_len(dev, 0);
	info->mem[0].memtype = UIO_MEM_PHYS;
	info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
	if (!info->mem[0].internal_addr)
		goto out_release;

	/* BAR2 */
	info->mem[1].name = "ADC, DAC, DIO";
	info->mem[1].addr = pci_resource_start(dev, 2);
	if (!info->mem[1].addr)
		goto out_unmap0;
	info->mem[1].size = pci_resource_len(dev, 2);
	info->mem[1].memtype = UIO_MEM_PHYS;
	info->mem[1].internal_addr = pci_ioremap_bar(dev, 2);
	if (!info->mem[1].internal_addr)
		goto out_unmap0;

	info->irq = dev->irq;
	info->irq_flags = IRQF_SHARED;
	info->handler = mf624_irq_handler;

	if (uio_register_device(&dev->dev, info))
		goto out_unmap1;

	pci_set_drvdata(dev, info);
	return 0;

out_unmap1:
	iounmap(info->mem[1].internal_addr);
out_unmap0:
	iounmap(info->mem[0].internal_addr);

out_release:
	pci_release_regions(dev);

out_disable:
	pci_disable_device(dev);

	return -ENODEV;
}

static void mf624_pci_remove(struct pci_dev *dev)
{
	struct uio_info *info = pci_get_drvdata(dev);

	mf624_disable_interrupt(ALL, info);

	uio_unregister_device(info);
	pci_release_regions(dev);
	pci_disable_device(dev);

	iounmap(info->mem[0].internal_addr);
	iounmap(info->mem[1].internal_addr);

	kfree(info);
}

static const struct pci_device_id mf624_pci_id[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF624) },
	{ 0, }
};

static struct pci_driver mf624_pci_driver = {
	.name = "mf624",
	.id_table = mf624_pci_id,
	.probe = mf624_pci_probe,
	.remove = mf624_pci_remove,
};
MODULE_DEVICE_TABLE(pci, mf624_pci_id);

int mf624_init(void)
{
	return pci_driver_register(&mf624_pci_driver);
}

void mf624_exit(void)
{
	pci_driver_unregister(&mf624_pci_driver);
}

module_init(mf624_init);
module_exit(mf624_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");
\end{lstlisting}

\newpage

Quellcode 2:

\begin{lstlisting}
/*
 * LEDs driver for the "User LED" on Routerboard532
 *
 * Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org>
 *
 * Based on leds-cobalt-qube.c by Florian Fainelly and
 * rb-diag.c (my own standalone driver for both LED and
 * button of Routerboard532).
 */

#include <linux/leds.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#include <asm/mach-rc32434/gpio.h>
#include <asm/mach-rc32434/rb.h>

static void rb532_led_set(struct led_classdev *cdev,
			  enum led_brightness brightness)
{
	if (brightness)
		set_latch_u5(LO_ULED, 0);

	else
		set_latch_u5(0, LO_ULED);
}

static enum led_brightness rb532_led_get(struct led_classdev *cdev)
{
	return (get_latch_u5() & LO_ULED) ? LED_FULL : LED_OFF;
}

static struct led_classdev rb532_uled = {
	.name = "uled",
	.brightness_set = rb532_led_set,
	.brightness_get = rb532_led_get,
	.default_trigger = "nand-disk",
};

static int rb532_led_probe(struct platform_device *pdev)
{
	return led_classdev_register(&pdev->dev, &rb532_uled);
}

static int rb532_led_remove(struct platform_device *pdev)
{
	led_classdev_unregister(&rb532_uled);
	return 0;
}

static struct platform_driver rb532_led_driver = {
	.probe = rb532_led_probe,
	.remove = rb532_led_remove,
	.driver = {
		.name = "rb532-led",
	},
};

module_platform_driver(rb532_led_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("User LED support for Routerboard532");
MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
MODULE_ALIAS("platform:rb532-led");
\end{lstlisting}
\end{appendix}
\end{document}
