diff options
Diffstat (limited to 'kernel-devel/linux-device')
| -rw-r--r-- | kernel-devel/linux-device/Makefile | 9 | ||||
| -rw-r--r-- | kernel-devel/linux-device/hints_linux-device_en.tex | 15 | ||||
| -rw-r--r-- | kernel-devel/linux-device/my_example.patch | 122 | ||||
| -rw-r--r-- | kernel-devel/linux-device/pres_linux-device_en.tex | 236 |
4 files changed, 382 insertions, 0 deletions
diff --git a/kernel-devel/linux-device/Makefile b/kernel-devel/linux-device/Makefile new file mode 100644 index 0000000..be2c24b --- /dev/null +++ b/kernel-devel/linux-device/Makefile @@ -0,0 +1,9 @@ +all: + for pdf in `ls -1 *.tex` ; do \ + TEXINPUTS=`pwd`:`pwd`/../..:.:..:$(TEXINPUTS) pdflatex $$pdf; \ + TEXINPUTS=`pwd`:`pwd`/../..:.:..:$(TEXINPUTS) pdflatex $$pdf; \ + done + +clean: + rm -f *.aux *.log *.pdf *.log *.snm *.toc *.vrb *.nav *.out + diff --git a/kernel-devel/linux-device/hints_linux-device_en.tex b/kernel-devel/linux-device/hints_linux-device_en.tex new file mode 100644 index 0000000..20174ab --- /dev/null +++ b/kernel-devel/linux-device/hints_linux-device_en.tex @@ -0,0 +1,15 @@ +\documentclass{article} +\usepackage{german} +\usepackage[utf8]{inputenc} + +\begin{document} + +\section*{Linux Device Structure\rq} + +\subsection*{Lernziele} +\begin{itemize} +\item Sinn und Zweck von 'struct device' +\item wichtige Funktionen in Verbindung mit 'struct device' +\end{itemize} + +\end{document} diff --git a/kernel-devel/linux-device/my_example.patch b/kernel-devel/linux-device/my_example.patch new file mode 100644 index 0000000..6e66c14 --- /dev/null +++ b/kernel-devel/linux-device/my_example.patch @@ -0,0 +1,122 @@ +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index c779509..43ae42d 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -51,6 +51,11 @@ config AD525X_DPOT_SPI + To compile this driver as a module, choose M here: the + module will be called ad525x_dpot-spi. + ++config MY ++ tristate "my driver example" ++ help ++ just an example for a simple driver dummy ++ + config ATMEL_PWM + tristate "Atmel AT32/AT91 PWM support" + depends on HAVE_CLK +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 3e1d801..614a3a2 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o + obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o + obj-$(CONFIG_INTEL_MID_PTI) += pti.o + obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o ++obj-$(CONFIG_MY) += my.o + obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o + obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o + obj-$(CONFIG_BMP085) += bmp085.o +diff --git a/drivers/misc/my.c b/drivers/misc/my.c +new file mode 100644 +index 0000000..49759ad +--- /dev/null ++++ b/drivers/misc/my.c +@@ -0,0 +1,88 @@ ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++ ++#define DEVICE_NAME "mydev" ++static struct class *dummy; ++ ++static ssize_t my_show_ro(struct device *my_dev, ++ struct device_attribute *my_attr, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, "%s\n", "show some cool value"); ++} ++ ++static ssize_t my_show_rw(struct device *my_dev, ++ struct device_attribute *my_attr, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, "%s\n", "write value and look at dmesg"); ++} ++ ++static ssize_t my_store_rw(struct device *my_dev, ++ struct device_attribute *my_attr, const char *buf, size_t count) ++{ ++ printk(KERN_ERR "my_store_rw: %s", buf); ++ return count; ++} ++ ++static DEVICE_ATTR(ro, S_IRUGO, my_show_ro, NULL); ++static DEVICE_ATTR(rw, S_IWUSR | S_IRUGO, my_show_rw, my_store_rw); ++ ++static struct attribute *my_dev_attrs[] = { ++ &dev_attr_ro.attr, ++ &dev_attr_rw.attr, ++ NULL, ++}; ++ ++static struct attribute_group my_dev_attr_group = { ++ .attrs = my_dev_attrs, ++}; ++ ++static const struct attribute_group *my_dev_attr_groups[] = { ++ &my_dev_attr_group, ++ NULL, ++}; ++ ++static struct device my_dev = { ++ .init_name = "mydevice", ++}; ++ ++static int __init my_init(void) ++{ ++ int ret = 0; ++ ++ dummy = class_create(THIS_MODULE, "dummy"); ++ device_initialize(&my_dev); ++ my_dev.groups = my_dev_attr_groups; ++ my_dev.parent = NULL; ++ my_dev.bus = NULL; ++ my_dev.class = dummy; ++ ret = device_add(&my_dev); ++ if (ret) { ++ printk(KERN_ERR "my: device register failed\n"); ++ goto failed_dev; ++ } ++ return 0; ++ ++failed_dev: ++ device_del(&my_dev); ++ class_destroy(dummy); ++ ++ return ret; ++} ++ ++static void __exit my_exit(void) ++{ ++ device_del(&my_dev); ++ class_destroy(dummy); ++} ++ ++MODULE_AUTHOR("Manuel Traut"); ++MODULE_DESCRIPTION("just my example"); ++MODULE_VERSION("20120412"); ++MODULE_LICENSE("GPL"); ++ ++module_init(my_init); ++module_exit(my_exit); diff --git a/kernel-devel/linux-device/pres_linux-device_en.tex b/kernel-devel/linux-device/pres_linux-device_en.tex new file mode 100644 index 0000000..da4ca55 --- /dev/null +++ b/kernel-devel/linux-device/pres_linux-device_en.tex @@ -0,0 +1,236 @@ +\input{configpres} + +\title{struct device} +\maketitle + +\subsection{basics} + +\begin{frame} +\frametitle{aim} +\begin{itemize} +\item lowest level representation of every device in a Linux system +\item hosts information that the device model core needs to model the system +\item most subsystems track additional information about the devices they host +\item it is rare for devices to be represented by bare device structures +\item this struct is usually embedded within higher-level representation of + the device +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{name and type} +for example a mouse device +\begin{tiny} +\begin{lstlisting}[frame=trBL] +include/linux/device.h: +... +struct device { + ... + const char *init_name; + const struct device_type *type; + ... +\end{lstlisting} +\end{tiny} +\end{frame} + +\begin{frame}[fragile] +\frametitle{connection of multiple devices} +for example usb-hostcontroller1/usb-device3/usb-endpoint4/mouse +\begin{tiny} +\begin{lstlisting}[frame=trBL] +include/linux/device.h: +... +struct device { + ... + struct device *parent; + ... +\end{lstlisting} +\end{tiny} +\begin{itemize} +\item 'parent' is a ptr to the device to which this device is attached +\item normaly a parent device is some sort of bus or host controller +\item If parent is NULL, the device, is a top-level device, which is not + usually what you want +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{private data} +\begin{tiny} +\begin{lstlisting}[frame=trBL] +drivers/base/base.h +... +struct device_private { + struct klist klist_children; //containing all children of this device + struct klist_node knode_parent; //node in sibling list + struct klist_node knode_driver; //node in driver list + struct klist_node knode_bus; //node in bus list + struct list_head deferred_probe;//entry in deferred_probe_list + void *driver_data; //private pointer for driver specific info + struct device *device; //pointer back to the device +}; +... +include/linux/device.h: +... +struct device { + ... + struct device_private *p; + ... +\end{lstlisting} +\end{tiny} +\end{frame} + +\begin{frame}[fragile] +\frametitle{bus} +\begin{tiny} +\begin{lstlisting}[frame=trBL] +include/linux/device.h: +... +struct device { + ... + struct bus_type *bus; + ... +\end{lstlisting} +\end{tiny} +\begin{itemize} +\item used by driver core to link between bus - device +\item hosts pointer for: probe, remove, suspend, \dots +\item these functions are called by the driver core on bus state changes +\item bus drivers need to implement these calls and normaly redirect them to + the associated devices +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{driver} +\begin{tiny} +\begin{lstlisting}[frame=trBL] +include/linux/device.h: +... +struct device { + ... + struct device_driver *driver; + ... +\end{lstlisting} +\end{tiny} +\begin{itemize} +\item used by driver core to link between driver - device +\item hosts a table of device id, the driver is responsible for +\item hosts pointer for: probe, remove, suspend, \dots +\item these functions are called by the bus driver on bus state changes +\item device drivers need to implement these calls +\item e.g. after a succesful probe call a driver is responsible for a device +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{platform data} +\begin{tiny} +\begin{lstlisting}[frame=trBL] +include/linux/device.h: +... +struct device { + ... + void *platform_data; + ... +\end{lstlisting} +\end{tiny} +\begin{itemize} +\item structure is declared by the platform device driver +\item structure is normally initialized by 'board support package' +\item hosts for example how a specific device is connected (mem\_base, irq) +\item can host informations about chip variants +\item shrinks 'board support packages' +\item reduces board specific \#ifdefs in driver code +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{misc} +\begin{itemize} +\item structs for device power management +\item ptr to NUMA node this device is close to +\item structs for DMA handling (if device is DMA capable) +\item information about associated device node(s) (/dev/huhu) +\item unique device id +\item lock to protect device resources +\item pointer to release() function of the device +\end{itemize} +\end{frame} + +\subsection{how is it used} + +\begin{frame}[fragile] +\frametitle{initialization} +The bus driver that discovers the device uses this to register the device with +the core: +\begin{tiny} +\begin{lstlisting}[frame=trBL] +int device_register(struct device * dev); +\end{lstlisting} +\end{tiny} +these fields should be initialized before calling the register function: +\begin{itemize} +\item parent +\item name +\item bus +\item class +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{use by a driver} +A device is removed from the core when its reference count goes to 0. +The reference count can be adjusted using: +\begin{tiny} +\begin{lstlisting}[frame=trBL] +struct device * get_device(struct device * dev); +void put_device(struct device * dev); +\end{lstlisting} +\end{tiny} +The device lock can be accessed by: +\begin{tiny} +\begin{lstlisting}[frame=trBL] +void lock_device(struct device * dev); +void unlock_device(struct device * dev); +\end{lstlisting} +\end{tiny} +\end{frame} + +\begin{frame}[fragile] +\frametitle{device attributes} +Attributes can be exported to sysfs by the device driver. +\begin{tiny} +\begin{lstlisting}[frame=trBL] +my.c: +... +static DEVICE_ATTR(ro_example, 0444, my_show_ro, NULL); +static DEVICE_ATTR(rw_example, 0644, my_show_rw, my_store_rw); + +static struct attribute *my_dev_attrs[] = { + &dev_attr_ro_example.attr, + &dev_attr_rw_example.attr, + NULL, +}; + +static struct attribute_group my_dev_attr_group = { + .attrs = my_dev_attrs, +}; + +static const struct attribute_group *my_dev_attr_groups[] = { + &my_dev_attr_group, + NULL, +}; + +static int __init my_driver_init(struct device *my_dev) +{ + ... + my_dev->groups = my_dev_attr_groups; + device_register(my_dev); + ... +} +\end{lstlisting} +\end{tiny} +\end{frame} + +\input{tailpres} |
