\documentclass[addpoints,12pt]{exam}

\usepackage{ngerman}
\usepackage{listings,color}
\usepackage{graphicx}
\usepackage[T1]{fontenc}

\firstpageheadrule
\runningheadrule
\lhead{Manuel Traut\\Sommersemester 2018}
\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{10. Juli 2018 10:30 Uhr}
\maketitle
\begin{center}
Hochschule Ravensburg-Weingarten
\vspace{1cm}

Raum: H142

Dauer: 60 Minuten, erlaubte Hilfsmittel: alle
\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 IoT Toaster entwickelt. Um die Sensoren (Temperatur,
  Luftfeuchtigkeit, Strommesser, Spannungsmesser, Lagemesser, sowie zwei
  Wegsensoren) und Aktoren (je eine PWM für Heizspirale und die zwei Motoren)
  des Toasters vom User-space zugreifbar zu machen haben Sie den Linuxkernel
  um entsprechende Treiber erweitert. Die Toasterapplikation im Userspace
  liest die Sensordaten aus und übermittelt Sie über ein Netzwerkinterface
  und WLAN Kerneltreiber in eine Cloudapplikation. Ausserdem ermöglicht die
  Toasterapplikation, dass in der Cloud definierte Toastprogramme (z.B.
  auftauen, bräunen, Holzkohle) die PWMs via Userspaceinterface programmieren.
  Die Toasterapplikation ist in JAVA geschrieben und verwendet ausschliesslich
  JAVA Module welche unter MIT oder LGPL Lizenz stehen.

\begin{parts}

\part[4] Argumentieren Sie weshalb es f\"ur zuk\"unftige Entwicklungen am
  Toaster f\"ur Ihre Firma von Vorteil ist, die neu entwickelten Kerneltreiber
  in den 'mainline Kernel' zu integrieren.

\part[6] Sie wollen Ihre Treiber welche Sie gegen Kernelversion 4.5 entwickelt
  haben in Mainline Linux integriert haben. Wie gehen Sie vor?

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

\part[12] Für die Temperatursensoren können Sie die Funktionen des 'thermal
  Subsystems' nutzen. Für den Luftfeuchtigkeitssensor gibt es kein passendes
  Subsystem. Der Sensor befindet sich auf einer PCI Karte, der Sensorwert
  (uint\_8) kann ohne Umrechnung von Memoryoffset 0x100 von PCI Bar 2 im Kernel
  gelesen werden.

	Verwenden Sie zur Beantwortung der folgenden Punkte Pseudocode oder
	beschreiben Sie textuell:

	\begin{enumerate}
		\item Was tut Ihre init Funktion?
		\item Was implementieren Sie in der probe Funktion?
		\item Wie ermöglichen Sie den Zugriff auf den Messwert vom Userspace aus?
		\item Beschreiben Sie wie Sie den Wert in der Toasterapplikation auslesen.
	\end{enumerate}


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

\part[1] M\"ussen Sie auf Anfrage eines Käufers die verwendeten Kernelsourcen
  zur Verf\"ugung stellen?

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

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

\question [6] Ein von Ihnen entwickelter Kerneltreiber funktioniert nicht wie
erwartet. Welche Debugingm\"oglichkeiten haben Sie?

Nennen Sie zwei Möglichkeiten und beschreiben Sie Vor- und Nachteile

\newpage

\question Im Linux Source gibt es einen Ordner 'staging'.
\begin{parts}
\part[1] Was findet man in diesem Ordner?
\part[2] Wann wird der Code aus diesem Ordner gel\"oscht / verschoben?
\end{parts}

\question

\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[6] Suchen Sie sich drei Codezeilen aus, erkl\"aren Sie jeweils in welchem
	Zusammenhang die Codezeile ausgeführt wird und was diese bewirkt.
\end{parts}

\question
Die folgenden Frage bezieht 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}
