<!DOCTYPE html>
<html lang="en" data-content_root="../../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Linux for S/390 and zSeries — The Linux Kernel documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css?v=3918102e" />
<script src="../../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../../_static/doctools.js?v=9bcbadda"></script>
<script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="IBM 3270 Display System support" href="3270.html" />
<link rel="prev" title="s390 Architecture" href="index.html" />
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../../index.html">
<img class="logo" src="../../_static/logo.svg" alt="Logo of The Linux Kernel"/>
</a></p>
<h1 class="logo"><a href="../../index.html">The Linux Kernel</a></h1>
<p class="blurb">6.18.50</p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<p>
<h3 class="kernel-toc-contents">Contents</h3>
<input type="checkbox" class="kernel-toc-toggle" id = "kernel-toc-toggle" checked>
<label class="kernel-toc-title" for="kernel-toc-toggle"></label>
<div class="kerneltoc" id="kerneltoc">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../process/development-process.html">Development process</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/submitting-patches.html">Submitting patches</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/code-of-conduct.html">Code of conduct</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../maintainer/index.html">Maintainer handbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/index.html">All development-process docs</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../core-api/index.html">Core API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../driver-api/index.html">Driver APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../subsystem-apis.html">Subsystems</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../locking/index.html">Locking</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../process/license-rules.html">Licensing rules</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../doc-guide/index.html">Writing documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev-tools/index.html">Development tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev-tools/testing-overview.html">Testing guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../kernel-hacking/index.html">Hacking guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../trace/index.html">Tracing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../fault-injection/index.html">Fault injection</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../livepatch/index.html">Livepatching</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../rust/index.html">Rust</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../admin-guide/index.html">Administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../kbuild/index.html">Build system</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../admin-guide/reporting-issues.html">Reporting issues</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../tools/index.html">Userspace tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../userspace-api/index.html">Userspace API</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../firmware-guide/index.html">Firmware</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../devicetree/index.html">Firmware and Devicetree</a></li>
</ul>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">CPU architectures</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../arc/index.html">ARC architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arm/index.html">ARM Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arm64/index.html">ARM64 Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../loongarch/index.html">LoongArch Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../m68k/index.html">m68k Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mips/index.html">MIPS-specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nios2/index.html">Nios II Specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../openrisc/index.html">OpenRISC Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../parisc/index.html">PA-RISC Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../powerpc/index.html">powerpc</a></li>
<li class="toctree-l2"><a class="reference internal" href="../riscv/index.html">RISC-V architecture</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">s390 Architecture</a><ul class="current">
<li class="toctree-l3 current"><a class="current reference internal" href="#">Linux for S/390 and zSeries</a></li>
<li class="toctree-l3"><a class="reference internal" href="3270.html">IBM 3270 Display System support</a></li>
<li class="toctree-l3"><a class="reference internal" href="driver-model.html">S/390 driver model interfaces</a></li>
<li class="toctree-l3"><a class="reference internal" href="mm.html">Memory Management</a></li>
<li class="toctree-l3"><a class="reference internal" href="monreader.html">Linux API for read access to z/VM Monitor Records</a></li>
<li class="toctree-l3"><a class="reference internal" href="qeth.html">IBM s390 QDIO Ethernet Driver</a></li>
<li class="toctree-l3"><a class="reference internal" href="s390dbf.html">S390 Debug Feature</a></li>
<li class="toctree-l3"><a class="reference internal" href="vfio-ap.html">Adjunct Processor (AP) facility</a></li>
<li class="toctree-l3"><a class="reference internal" href="vfio-ap-locking.html">VFIO AP Locks Overview</a></li>
<li class="toctree-l3"><a class="reference internal" href="vfio-ccw.html">vfio-ccw: the basic infrastructure</a></li>
<li class="toctree-l3"><a class="reference internal" href="zfcpdump.html">The s390 SCSI dump tool (zfcpdump)</a></li>
<li class="toctree-l3"><a class="reference internal" href="common_io.html">S/390 common I/O-Layer</a></li>
<li class="toctree-l3"><a class="reference internal" href="pci.html">S/390 PCI</a></li>
<li class="toctree-l3"><a class="reference internal" href="text_files.html">ibm 3270 changelog</a></li>
<li class="toctree-l3"><a class="reference internal" href="text_files.html#ibm-3270-config3270-sh">ibm 3270 config3270.sh</a></li>
<li class="toctree-l3"><a class="reference internal" href="features.html">Feature status on s390 architecture</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../sh/index.html">SuperH Interfaces Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sparc/index.html">Sparc Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../x86/index.html">x86-specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../xtensa/index.html">Xtensa Architecture</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../staging/index.html">Unsorted documentation</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../translations/index.html">Translations</a></li>
</ul>
</div>
<script type="text/javascript"> <!--
var sbar = document.getElementsByClassName("sphinxsidebar")[0];
let currents = document.getElementsByClassName("current")
if (currents.length) {
sbar.scrollTop = currents[currents.length - 1].offsetTop;
}
--> </script>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../../_sources/arch/s390/cds.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="linux-for-s-390-and-zseries">
<h1>Linux for S/390 and zSeries<a class="headerlink" href="#linux-for-s-390-and-zseries" title="Link to this heading">¶</a></h1>
<p>Common Device Support (CDS)
Device Driver I/O Support Routines</p>
<dl class="simple">
<dt>Authors:</dt><dd><ul class="simple">
<li><p>Ingo Adlung</p></li>
<li><p>Cornelia Huck</p></li>
</ul>
</dd>
</dl>
<p>Copyright, IBM Corp. 1999-2002</p>
<section id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Link to this heading">¶</a></h2>
<p>This document describes the common device support routines for Linux/390.
Different than other hardware architectures, ESA/390 has defined a unified
I/O access method. This gives relief to the device drivers as they don’t
have to deal with different bus types, polling versus interrupt
processing, shared versus non-shared interrupt processing, DMA versus port
I/O (PIO), and other hardware features more. However, this implies that
either every single device driver needs to implement the hardware I/O
attachment functionality itself, or the operating system provides for a
unified method to access the hardware, providing all the functionality that
every single device driver would have to provide itself.</p>
<p>The document does not intend to explain the ESA/390 hardware architecture in
every detail.This information can be obtained from the ESA/390 Principles of
Operation manual (IBM Form. No. SA22-7201).</p>
<p>In order to build common device support for ESA/390 I/O interfaces, a
functional layer was introduced that provides generic I/O access methods to
the hardware.</p>
<p>The common device support layer comprises the I/O support routines defined
below. Some of them implement common Linux device driver interfaces, while
some of them are ESA/390 platform specific.</p>
<dl class="simple">
<dt>Note:</dt><dd><p>In order to write a driver for S/390, you also need to look into the interface
described in <a class="reference internal" href="driver-model.html"><span class="doc">S/390 driver model interfaces</span></a>.</p>
</dd>
</dl>
<p>Note for porting drivers from 2.4:</p>
<p>The major changes are:</p>
<ul class="simple">
<li><p>The functions use a ccw_device instead of an irq (subchannel).</p></li>
<li><p>All drivers must define a ccw_driver (see <a class="reference internal" href="driver-model.html"><span class="doc">S/390 driver model interfaces</span></a>) and the associated
functions.</p></li>
<li><p><a class="reference internal" href="../../core-api/genericirq.html#c.request_irq" title="request_irq"><code class="xref c c-func docutils literal notranslate"><span class="pre">request_irq()</span></code></a> and <a class="reference internal" href="../../core-api/genericirq.html#c.free_irq" title="free_irq"><code class="xref c c-func docutils literal notranslate"><span class="pre">free_irq()</span></code></a> are no longer done by the driver.</p></li>
<li><p>The oper_handler is (kindof) replaced by the <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">probe()</span></code> and <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">set_online()</span></code> functions
of the ccw_driver.</p></li>
<li><p>The not_oper_handler is (kindof) replaced by the <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">remove()</span></code> and <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">set_offline()</span></code>
functions of the ccw_driver.</p></li>
<li><p>The channel device layer is gone.</p></li>
<li><p>The interrupt handlers must be adapted to use a ccw_device as argument.
Moreover, they don’t return a devstat, but an irb.</p></li>
<li><p>Before initiating an io, the options must be set via <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_set_options" title="ccw_device_set_options"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_set_options()</span></code></a>.</p></li>
<li><p>Instead of calling <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">read_dev_chars()</span></code>/<code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">read_conf_data()</span></code>, the driver issues
the channel program and handles the interrupt itself.</p></li>
</ul>
<dl class="simple">
<dt>ccw_device_get_ciw()</dt><dd><p>get commands from extended sense data.</p>
</dd>
<dt>ccw_device_start(), ccw_device_start_timeout(), ccw_device_start_key(), ccw_device_start_key_timeout()</dt><dd><p>initiate an I/O request.</p>
</dd>
<dt>ccw_device_resume()</dt><dd><p>resume channel program execution.</p>
</dd>
<dt>ccw_device_halt()</dt><dd><p>terminate the current I/O request processed on the device.</p>
</dd>
<dt>do_IRQ()</dt><dd><p>generic interrupt routine. This function is called by the interrupt entry
routine whenever an I/O interrupt is presented to the system. The <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">do_IRQ()</span></code>
routine determines the interrupt status and calls the device specific
interrupt handler according to the rules (flags) defined during I/O request
initiation with <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">do_IO()</span></code>.</p>
</dd>
</dl>
<p>The next chapters describe the functions other than <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">do_IRQ()</span></code> in more details.
The <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">do_IRQ()</span></code> interface is not described, as it is called from the Linux/390
first level interrupt handler only and does not comprise a device driver
callable interface. Instead, the functional description of <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">do_IO()</span></code> also
describes the input to the device specific interrupt handler.</p>
<dl class="simple">
<dt>Note:</dt><dd><p>All explanations apply also to the 64 bit architecture s390x.</p>
</dd>
</dl>
</section>
<section id="common-device-support-cds-for-linux-390-device-drivers">
<h2>Common Device Support (CDS) for Linux/390 Device Drivers<a class="headerlink" href="#common-device-support-cds-for-linux-390-device-drivers" title="Link to this heading">¶</a></h2>
<section id="general-information">
<h3>General Information<a class="headerlink" href="#general-information" title="Link to this heading">¶</a></h3>
<p>The following chapters describe the I/O related interface routines the
Linux/390 common device support (CDS) provides to allow for device specific
driver implementations on the IBM ESA/390 hardware platform. Those interfaces
intend to provide the functionality required by every device driver
implementation to allow to drive a specific hardware device on the ESA/390
platform. Some of the interface routines are specific to Linux/390 and some
of them can be found on other Linux platforms implementations too.
Miscellaneous function prototypes, data declarations, and macro definitions
can be found in the architecture specific C header file
linux/arch/s390/include/asm/irq.h.</p>
</section>
<section id="overview-of-cds-interface-concepts">
<h3>Overview of CDS interface concepts<a class="headerlink" href="#overview-of-cds-interface-concepts" title="Link to this heading">¶</a></h3>
<p>Different to other hardware platforms, the ESA/390 architecture doesn’t define
interrupt lines managed by a specific interrupt controller and bus systems
that may or may not allow for shared interrupts, DMA processing, etc.. Instead,
the ESA/390 architecture has implemented a so called channel subsystem, that
provides a unified view of the devices physically attached to the systems.
Though the ESA/390 hardware platform knows about a huge variety of different
peripheral attachments like disk devices (aka. DASDs), tapes, communication
controllers, etc. they can all be accessed by a well defined access method and
they are presenting I/O completion a unified way : I/O interruptions. Every
single device is uniquely identified to the system by a so called subchannel,
where the ESA/390 architecture allows for 64k devices be attached.</p>
<p>Linux, however, was first built on the Intel PC architecture, with its two
cascaded 8259 programmable interrupt controllers (PICs), that allow for a
maximum of 15 different interrupt lines. All devices attached to such a system
share those 15 interrupt levels. Devices attached to the ISA bus system must
not share interrupt levels (aka. IRQs), as the ISA bus bases on edge triggered
interrupts. MCA, EISA, PCI and other bus systems base on level triggered
interrupts, and therewith allow for shared IRQs. However, if multiple devices
present their hardware status by the same (shared) IRQ, the operating system
has to call every single device driver registered on this IRQ in order to
determine the device driver owning the device that raised the interrupt.</p>
<p>Up to kernel 2.4, Linux/390 used to provide interfaces via the IRQ (subchannel).
For internal use of the common I/O layer, these are still there. However,
device drivers should use the new calling interface via the ccw_device only.</p>
<p>During its startup the Linux/390 system checks for peripheral devices. Each
of those devices is uniquely defined by a so called subchannel by the ESA/390
channel subsystem. While the subchannel numbers are system generated, each
subchannel also takes a user defined attribute, the so called device number.
Both subchannel number and device number cannot exceed 65535. During sysfs
initialisation, the information about control unit type and device types that
imply specific I/O commands (channel command words - CCWs) in order to operate
the device are gathered. Device drivers can retrieve this set of hardware
information during their initialization step to recognize the devices they
support using the information saved in the <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device" title="ccw_device"><code class="xref c c-struct docutils literal notranslate"><span class="pre">struct</span> <span class="pre">ccw_device</span></code></a> given to them.
This methods implies that Linux/390 doesn’t require to probe for free (not
armed) interrupt request lines (IRQs) to drive its devices with. Where
applicable, the device drivers can use issue the READ DEVICE CHARACTERISTICS
ccw to retrieve device characteristics in its online routine.</p>
<p>In order to allow for easy I/O initiation the CDS layer provides a
<a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> interface that takes a device specific channel program (one
or more CCWs) as input sets up the required architecture specific control blocks
and initiates an I/O request on behalf of the device driver. The
<a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> routine allows to specify whether it expects the CDS layer
to notify the device driver for every interrupt it observes, or with final status
only. See <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> for more details. A device driver must never issue
ESA/390 I/O commands itself, but must use the Linux/390 CDS interfaces instead.</p>
<p>For long running I/O request to be canceled, the CDS layer provides the
<a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a> function. Some devices require to initially issue a HALT
SUBCHANNEL (HSCH) command without having pending I/O requests. This function is
also covered by <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a>.</p>
<p><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">get_ciw()</span></code> - get command information word</p>
<p>This call enables a device driver to get information about supported commands
from the extended SenseID data.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>struct ciw *
ccw_device_get_ciw(struct ccw_device *cdev, __u32 cmd);
</pre></div>
</div>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>cdev</p></td>
<td><p>The ccw_device for which the command is to be retrieved.</p></td>
</tr>
<tr class="row-even"><td><p>cmd</p></td>
<td><p>The command type to be retrieved.</p></td>
</tr>
</tbody>
</table>
<p><a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_get_ciw" title="ccw_device_get_ciw"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_get_ciw()</span></code></a> returns:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>NULL</p></td>
<td><p>No extended data available, invalid device or command not found.</p></td>
</tr>
<tr class="row-even"><td><p>!NULL</p></td>
<td><p>The command requested.</p></td>
</tr>
</tbody>
</table>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ccw_device_start() - Initiate I/O Request
</pre></div>
</div>
<p>The <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> routines is the I/O request front-end processor. All
device driver I/O requests must be issued using this routine. A device driver
must not issue ESA/390 I/O commands itself. Instead the <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a>
routine provides all interfaces required to drive arbitrary devices.</p>
<p>This description also covers the status information passed to the device
driver’s interrupt handler as this is related to the rules (flags) defined
with the associated I/O request when calling <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int ccw_device_start(struct ccw_device *cdev,
struct ccw1 *cpa,
unsigned long intparm,
__u8 lpm,
unsigned long flags);
int ccw_device_start_timeout(struct ccw_device *cdev,
struct ccw1 *cpa,
unsigned long intparm,
__u8 lpm,
unsigned long flags,
int expires);
int ccw_device_start_key(struct ccw_device *cdev,
struct ccw1 *cpa,
unsigned long intparm,
__u8 lpm,
__u8 key,
unsigned long flags);
int ccw_device_start_key_timeout(struct ccw_device *cdev,
struct ccw1 *cpa,
unsigned long intparm,
__u8 lpm,
__u8 key,
unsigned long flags,
int expires);
</pre></div>
</div>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>cdev</p></td>
<td><p>ccw_device the I/O is destined for</p></td>
</tr>
<tr class="row-even"><td><p>cpa</p></td>
<td><p>logical start address of channel program</p></td>
</tr>
<tr class="row-odd"><td><p>user_intparm</p></td>
<td><p>user specific interrupt information; will be presented
back to the device driver’s interrupt handler. Allows a
device driver to associate the interrupt with a
particular I/O request.</p></td>
</tr>
<tr class="row-even"><td><p>lpm</p></td>
<td><p>defines the channel path to be used for a specific I/O
request. A value of 0 will make cio use the opm.</p></td>
</tr>
<tr class="row-odd"><td><p>key</p></td>
<td><p>the storage key to use for the I/O (useful for operating on a
storage with a storage key != default key)</p></td>
</tr>
<tr class="row-even"><td><p>flag</p></td>
<td><p>defines the action to be performed for I/O processing</p></td>
</tr>
<tr class="row-odd"><td><p>expires</p></td>
<td><p>timeout value in jiffies. The common I/O layer will terminate
the running program after this and call the interrupt handler
with ERR_PTR(-ETIMEDOUT) as irb.</p></td>
</tr>
</tbody>
</table>
<p>Possible flag values are:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>DOIO_ALLOW_SUSPEND</p></td>
<td><p>channel program may become suspended</p></td>
</tr>
<tr class="row-even"><td><p>DOIO_DENY_PREFETCH</p></td>
<td><p>don’t allow for CCW prefetch; usually
this implies the channel program might
become modified</p></td>
</tr>
<tr class="row-odd"><td><p>DOIO_SUPPRESS_INTER</p></td>
<td><p>don’t call the handler on intermediate status</p></td>
</tr>
</tbody>
</table>
<p>The cpa parameter points to the first format 1 CCW of a channel program:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>struct ccw1 {
__u8 cmd_code;/* command code */
__u8 flags; /* flags, like IDA addressing, etc. */
__u16 count; /* byte count */
__u32 cda; /* data address */
} __attribute__ ((packed,aligned(8)));
</pre></div>
</div>
<p>with the following CCW flags values defined:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>CCW_FLAG_DC</p></td>
<td><p>data chaining</p></td>
</tr>
<tr class="row-even"><td><p>CCW_FLAG_CC</p></td>
<td><p>command chaining</p></td>
</tr>
<tr class="row-odd"><td><p>CCW_FLAG_SLI</p></td>
<td><p>suppress incorrect length</p></td>
</tr>
<tr class="row-even"><td><p>CCW_FLAG_SKIP</p></td>
<td><p>skip</p></td>
</tr>
<tr class="row-odd"><td><p>CCW_FLAG_PCI</p></td>
<td><p>PCI</p></td>
</tr>
<tr class="row-even"><td><p>CCW_FLAG_IDA</p></td>
<td><p>indirect addressing</p></td>
</tr>
<tr class="row-odd"><td><p>CCW_FLAG_SUSPEND</p></td>
<td><p>suspend</p></td>
</tr>
</tbody>
</table>
<p>Via <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_set_options" title="ccw_device_set_options"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_set_options()</span></code></a>, the device driver may specify the following
options for the device:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>DOIO_EARLY_NOTIFICATION</p></td>
<td><p>allow for early interrupt notification</p></td>
</tr>
<tr class="row-even"><td><p>DOIO_REPORT_ALL</p></td>
<td><p>report all interrupt conditions</p></td>
</tr>
</tbody>
</table>
<p>The <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> function returns:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>0</p></td>
<td><p>successful completion or request successfully initiated</p></td>
</tr>
<tr class="row-even"><td><p>-EBUSY</p></td>
<td><p>The device is currently processing a previous I/O request, or there is
a status pending at the device.</p></td>
</tr>
<tr class="row-odd"><td><p>-ENODEV</p></td>
<td><p>cdev is invalid, the device is not operational or the ccw_device is
not online.</p></td>
</tr>
</tbody>
</table>
<p>When the I/O request completes, the CDS first level interrupt handler will
accumulate the status in a <a class="reference internal" href="../../driver-api/s390-drivers.html#c.irb" title="irb"><code class="xref c c-struct docutils literal notranslate"><span class="pre">struct</span> <span class="pre">irb</span></code></a> and then call the device interrupt handler.
The intparm field will contain the value the device driver has associated with a
particular I/O request. If a pending device status was recognized,
intparm will be set to 0 (zero). This may happen during I/O initiation or delayed
by an alert status notification. In any case this status is not related to the
current (last) I/O request. In case of a delayed status notification no special
interrupt will be presented to indicate I/O completion as the I/O request was
never started, even though <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> returned with successful completion.</p>
<p>The irb may contain an error value, and the device driver should check for this
first:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>-ETIMEDOUT</p></td>
<td><p>the common I/O layer terminated the request after the specified
timeout value</p></td>
</tr>
<tr class="row-even"><td><p>-EIO</p></td>
<td><p>the common I/O layer terminated the request due to an error state</p></td>
</tr>
</tbody>
</table>
<p>If the concurrent sense flag in the extended status word (esw) in the irb is
set, the field erw.scnt in the esw describes the number of device specific
sense bytes available in the extended control word irb->scsw.ecw[]. No device
sensing by the device driver itself is required.</p>
<p>The device interrupt handler can use the following definitions to investigate
the primary unit check source coded in sense byte 0 :</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>SNS0_CMD_REJECT</p></td>
<td><p>0x80</p></td>
</tr>
<tr class="row-even"><td><p>SNS0_INTERVENTION_REQ</p></td>
<td><p>0x40</p></td>
</tr>
<tr class="row-odd"><td><p>SNS0_BUS_OUT_CHECK</p></td>
<td><p>0x20</p></td>
</tr>
<tr class="row-even"><td><p>SNS0_EQUIPMENT_CHECK</p></td>
<td><p>0x10</p></td>
</tr>
<tr class="row-odd"><td><p>SNS0_DATA_CHECK</p></td>
<td><p>0x08</p></td>
</tr>
<tr class="row-even"><td><p>SNS0_OVERRUN</p></td>
<td><p>0x04</p></td>
</tr>
<tr class="row-odd"><td><p>SNS0_INCOMPL_DOMAIN</p></td>
<td><p>0x01</p></td>
</tr>
</tbody>
</table>
<p>Depending on the device status, multiple of those values may be set together.
Please refer to the device specific documentation for details.</p>
<p>The irb->scsw.cstat field provides the (accumulated) subchannel status :</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>SCHN_STAT_PCI</p></td>
<td><p>program controlled interrupt</p></td>
</tr>
<tr class="row-even"><td><p>SCHN_STAT_INCORR_LEN</p></td>
<td><p>incorrect length</p></td>
</tr>
<tr class="row-odd"><td><p>SCHN_STAT_PROG_CHECK</p></td>
<td><p>program check</p></td>
</tr>
<tr class="row-even"><td><p>SCHN_STAT_PROT_CHECK</p></td>
<td><p>protection check</p></td>
</tr>
<tr class="row-odd"><td><p>SCHN_STAT_CHN_DATA_CHK</p></td>
<td><p>channel data check</p></td>
</tr>
<tr class="row-even"><td><p>SCHN_STAT_CHN_CTRL_CHK</p></td>
<td><p>channel control check</p></td>
</tr>
<tr class="row-odd"><td><p>SCHN_STAT_INTF_CTRL_CHK</p></td>
<td><p>interface control check</p></td>
</tr>
<tr class="row-even"><td><p>SCHN_STAT_CHAIN_CHECK</p></td>
<td><p>chaining check</p></td>
</tr>
</tbody>
</table>
<p>The irb->scsw.dstat field provides the (accumulated) device status :</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>DEV_STAT_ATTENTION</p></td>
<td><p>attention</p></td>
</tr>
<tr class="row-even"><td><p>DEV_STAT_STAT_MOD</p></td>
<td><p>status modifier</p></td>
</tr>
<tr class="row-odd"><td><p>DEV_STAT_CU_END</p></td>
<td><p>control unit end</p></td>
</tr>
<tr class="row-even"><td><p>DEV_STAT_BUSY</p></td>
<td><p>busy</p></td>
</tr>
<tr class="row-odd"><td><p>DEV_STAT_CHN_END</p></td>
<td><p>channel end</p></td>
</tr>
<tr class="row-even"><td><p>DEV_STAT_DEV_END</p></td>
<td><p>device end</p></td>
</tr>
<tr class="row-odd"><td><p>DEV_STAT_UNIT_CHECK</p></td>
<td><p>unit check</p></td>
</tr>
<tr class="row-even"><td><p>DEV_STAT_UNIT_EXCEP</p></td>
<td><p>unit exception</p></td>
</tr>
</tbody>
</table>
<p>Please see the ESA/390 Principles of Operation manual for details on the
individual flag meanings.</p>
<p>Usage Notes:</p>
<p><a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> must be called disabled and with the ccw device lock held.</p>
<p>The device driver is allowed to issue the next <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> call from
within its interrupt handler already. It is not required to schedule a
bottom-half, unless a non deterministically long running error recovery procedure
or similar needs to be scheduled. During I/O processing the Linux/390 generic
I/O device driver support has already obtained the IRQ lock, i.e. the handler
must not try to obtain it again when calling <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> or we end in a
deadlock situation!</p>
<p>If a device driver relies on an I/O request to be completed prior to start the
next it can reduce I/O processing overhead by chaining a NoOp I/O command
CCW_CMD_NOOP to the end of the submitted CCW chain. This will force Channel-End
and Device-End status to be presented together, with a single interrupt.
However, this should be used with care as it implies the channel will remain
busy, not being able to process I/O requests for other devices on the same
channel. Therefore e.g. read commands should never use this technique, as the
result will be presented by a single interrupt anyway.</p>
<p>In order to minimize I/O overhead, a device driver should use the
DOIO_REPORT_ALL only if the device can report intermediate interrupt
information prior to device-end the device driver urgently relies on. In this
case all I/O interruptions are presented to the device driver until final
status is recognized.</p>
<p>If a device is able to recover from asynchronously presented I/O errors, it can
perform overlapping I/O using the DOIO_EARLY_NOTIFICATION flag. While some
devices always report channel-end and device-end together, with a single
interrupt, others present primary status (channel-end) when the channel is
ready for the next I/O request and secondary status (device-end) when the data
transmission has been completed at the device.</p>
<p>Above flag allows to exploit this feature, e.g. for communication devices that
can handle lost data on the network to allow for enhanced I/O processing.</p>
<p>Unless the channel subsystem at any time presents a secondary status interrupt,
exploiting this feature will cause only primary status interrupts to be
presented to the device driver while overlapping I/O is performed. When a
secondary status without error (alert status) is presented, this indicates
successful completion for all overlapping <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> requests that have
been issued since the last secondary (final) status.</p>
<p>Channel programs that intend to set the suspend flag on a channel command word
(CCW) must start the I/O operation with the DOIO_ALLOW_SUSPEND option or the
suspend flag will cause a channel program check. At the time the channel program
becomes suspended an intermediate interrupt will be generated by the channel
subsystem.</p>
<p><a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_resume" title="ccw_device_resume"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_resume()</span></code></a> - Resume Channel Program Execution</p>
<p>If a device driver chooses to suspend the current channel program execution by
setting the CCW suspend flag on a particular CCW, the channel program execution
is suspended. In order to resume channel program execution the CIO layer
provides the <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_resume" title="ccw_device_resume"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_resume()</span></code></a> routine.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int ccw_device_resume(struct ccw_device *cdev);
</pre></div>
</div>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>cdev</p></td>
<td><p>ccw_device the resume operation is requested for</p></td>
</tr>
</tbody>
</table>
<p>The <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_resume" title="ccw_device_resume"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_resume()</span></code></a> function returns:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>0</p></td>
<td><p>suspended channel program is resumed</p></td>
</tr>
<tr class="row-even"><td><p>-EBUSY</p></td>
<td><p>status pending</p></td>
</tr>
<tr class="row-odd"><td><p>-ENODEV</p></td>
<td><p>cdev invalid or not-operational subchannel</p></td>
</tr>
<tr class="row-even"><td><p>-EINVAL</p></td>
<td><p>resume function not applicable</p></td>
</tr>
<tr class="row-odd"><td><p>-ENOTCONN</p></td>
<td><p>there is no I/O request pending for completion</p></td>
</tr>
</tbody>
</table>
<p>Usage Notes:</p>
<p>Please have a look at the <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_start" title="ccw_device_start"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_start()</span></code></a> usage notes for more details on
suspended channel programs.</p>
<p><a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a> - Halt I/O Request Processing</p>
<p>Sometimes a device driver might need a possibility to stop the processing of
a long-running channel program or the device might require to initially issue
a halt subchannel (HSCH) I/O command. For those purposes the <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a>
command is provided.</p>
<p><a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a> must be called disabled and with the ccw device lock held.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int ccw_device_halt(struct ccw_device *cdev,
unsigned long intparm);
</pre></div>
</div>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>cdev</p></td>
<td><p>ccw_device the halt operation is requested for</p></td>
</tr>
<tr class="row-even"><td><p>intparm</p></td>
<td><p>interruption parameter; value is only used if no I/O
is outstanding, otherwise the intparm associated with
the I/O request is returned</p></td>
</tr>
</tbody>
</table>
<p>The <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a> function returns:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>0</p></td>
<td><p>request successfully initiated</p></td>
</tr>
<tr class="row-even"><td><p>-EBUSY</p></td>
<td><p>the device is currently busy, or status pending.</p></td>
</tr>
<tr class="row-odd"><td><p>-ENODEV</p></td>
<td><p>cdev invalid.</p></td>
</tr>
<tr class="row-even"><td><p>-EINVAL</p></td>
<td><p>The device is not operational or the ccw device is not online.</p></td>
</tr>
</tbody>
</table>
<p>Usage Notes:</p>
<p>A device driver may write a never-ending channel program by writing a channel
program that at its end loops back to its beginning by means of a transfer in
channel (TIC) command (CCW_CMD_TIC). Usually this is performed by network
device drivers by setting the PCI CCW flag (CCW_FLAG_PCI). Once this CCW is
executed a program controlled interrupt (PCI) is generated. The device driver
can then perform an appropriate action. Prior to interrupt of an outstanding
read to a network device (with or without PCI flag) a <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a>
is required to end the pending operation.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ccw_device_clear() - Terminage I/O Request Processing
</pre></div>
</div>
<p>In order to terminate all I/O processing at the subchannel, the clear subchannel
(CSCH) command is used. It can be issued via <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_clear" title="ccw_device_clear"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_clear()</span></code></a>.</p>
<p><a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_clear" title="ccw_device_clear"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_clear()</span></code></a> must be called disabled and with the ccw device lock held.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm);
</pre></div>
</div>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>cdev</p></td>
<td><p>ccw_device the clear operation is requested for</p></td>
</tr>
<tr class="row-even"><td><p>intparm</p></td>
<td><p>interruption parameter (see <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_halt" title="ccw_device_halt"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_halt()</span></code></a>)</p></td>
</tr>
</tbody>
</table>
<p>The <a class="reference internal" href="../../driver-api/s390-drivers.html#c.ccw_device_clear" title="ccw_device_clear"><code class="xref c c-func docutils literal notranslate"><span class="pre">ccw_device_clear()</span></code></a> function returns:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><p>0</p></td>
<td><p>request successfully initiated</p></td>
</tr>
<tr class="row-even"><td><p>-ENODEV</p></td>
<td><p>cdev invalid</p></td>
</tr>
<tr class="row-odd"><td><p>-EINVAL</p></td>
<td><p>The device is not operational or the ccw device is not online.</p></td>
</tr>
</tbody>
</table>
</section>
<section id="miscellaneous-support-routines">
<h3>Miscellaneous Support Routines<a class="headerlink" href="#miscellaneous-support-routines" title="Link to this heading">¶</a></h3>
<p>This chapter describes various routines to be used in a Linux/390 device
driver programming environment.</p>
<p><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">get_ccwdev_lock()</span></code></p>
<p>Get the address of the device specific lock. This is then used in
<code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">spin_lock()</span></code> / <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">spin_unlock()</span></code> calls.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>__u8 ccw_device_get_path_mask(struct ccw_device *cdev);
</pre></div>
</div>
<p>Get the mask of the path currently available for cdev.</p>
</section>
</section>
</section>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©The kernel development community.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.1.3</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="../../_sources/arch/s390/cds.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>