Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
###
# This makefile is used to generate the kernel documentation,
# primarily based on in-line comments in various source files.
# See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
# to ducument the SRC - and how to read it.
# To add a new book the only step required is to add the book to the
# list of DOCBOOKS.
DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-hacking.xml kernel-locking.xml via-audio.xml \
deviceiobook.xml procfs-guide.xml tulip-user.xml \
writing_usb_driver.xml scsidrivers.xml sis900.xml \
kernel-api.xml journal-api.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml
###
# The build process is as follows (targets):
# (xmldocs)
# file.tmpl --> file.xml +--> file.ps (psdocs)
# +--> file.pdf (pdfdocs)
# +--> DIR=file (htmldocs)
# +--> man/ (mandocs)
###
# The targets that may be used.
.PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
xmldocs: $(BOOKS)
sgmldocs: xmldocs
PS := $(patsubst %.xml, %.ps, $(BOOKS))
psdocs: $(PS)
PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
pdfdocs: $(PDF)
HTML := $(patsubst %.xml, %.html, $(BOOKS))
htmldocs: $(HTML)
MAN := $(patsubst %.xml, %.9, $(BOOKS))
mandocs: $(MAN)
installmandocs: mandocs
$(MAKEMAN) install Documentation/DocBook/man
###
#External programs used
KERNELDOC = scripts/kernel-doc
DOCPROC = scripts/basic/docproc
SPLITMAN = $(PERL) $(srctree)/scripts/split-man
MAKEMAN = $(PERL) $(srctree)/scripts/makeman
###
# DOCPROC is used for two purposes:
# 1) To generate a dependency list for a .tmpl file
# 2) To preprocess a .tmpl file and call kernel-doc with
# appropriate parameters.
# The following rules are used to generate the .xml documentation
# required to generate the final targets. (ps, pdf, html).
quiet_cmd_docproc = DOCPROC $@
cmd_docproc = SRCTREE=$(srctree)/ $(DOCPROC) doc $< >$@
define rule_docproc
set -e; \
$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))';) \
$(cmd_$(1)); \
( \
echo 'cmd_$@ := $(cmd_$(1))'; \
echo $@: `SRCTREE=$(srctree) $(DOCPROC) depend $<`; \
) > $(dir $@).$(notdir $@).cmd
endef
%.xml: %.tmpl FORCE
$(call if_changed_rule,docproc)
###
#Read in all saved dependency files
cmd_files := $(wildcard $(foreach f,$(BOOKS),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
include $(cmd_files)
endif
###
# Changes in kernel-doc force a rebuild of all documentation
$(BOOKS): $(KERNELDOC)
###
# procfs guide uses a .c file as example code.
# This requires an explicit dependency
C-procfs-example = procfs_example.xml
C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
$(obj)/procfs-guide.xml: $(C-procfs-example2)
###
# Rules to generate postscript, PDF and HTML
# db2html creates a directory. Generate a html file used for timestamp
quiet_cmd_db2ps = DB2PS $@
cmd_db2ps = db2ps -o $(dir $@) $<
%.ps : %.xml
@(which db2ps > /dev/null 2>&1) || \
(echo "*** You need to install DocBook stylesheets ***"; \
exit 1)
$(call cmd,db2ps)
quiet_cmd_db2pdf = DB2PDF $@
cmd_db2pdf = db2pdf -o $(dir $@) $<
%.pdf : %.xml
@(which db2pdf > /dev/null 2>&1) || \
(echo "*** You need to install DocBook stylesheets ***"; \
exit 1)
$(call cmd,db2pdf)
quiet_cmd_db2html = DB2HTML $@
cmd_db2html = db2html -o $(patsubst %.html,%,$@) $< && \
echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/book1.html"> \
Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
%.html: %.xml
@(which db2html > /dev/null 2>&1) || \
(echo "*** You need to install DocBook stylesheets ***"; \
exit 1)
@rm -rf $@ $(patsubst %.html,%,$@)
$(call cmd,db2html)
@if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
###
# Rule to generate man files - output is placed in the man subdirectory
%.9: %.xml
ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/Documentation/DocBook/man
endif
$(SPLITMAN) $< $(objtree)/Documentation/DocBook/man "$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)"
$(MAKEMAN) convert $(objtree)/Documentation/DocBook/man $<
###
# Rules to generate postscripts and PNG imgages from .fig format files
quiet_cmd_fig2eps = FIG2EPS $@
cmd_fig2eps = fig2dev -Leps $< $@
%.eps: %.fig
@(which fig2dev > /dev/null 2>&1) || \
(echo "*** You need to install transfig ***"; \
exit 1)
$(call cmd,fig2eps)
quiet_cmd_fig2png = FIG2PNG $@
cmd_fig2png = fig2dev -Lpng $< $@
%.png: %.fig
@(which fig2dev > /dev/null 2>&1) || \
(echo "*** You need to install transfig ***"; \
exit 1)
$(call cmd,fig2png)
###
# Rule to convert a .c file to inline XML documentation
%.xml: %.c
@echo ' GEN $@'
@( \
echo "<programlisting>"; \
expand --tabs=8 < $< | \
sed -e "s/&/\\&amp;/g" \
-e "s/</\\&lt;/g" \
-e "s/>/\\&gt;/g"; \
echo "</programlisting>") > $@
###
# Help targets as used by the top-level makefile
dochelp:
@echo ' Linux kernel internal documentation in different formats:'
@echo ' xmldocs (XML DocBook), psdocs (Postscript), pdfdocs (PDF)'
@echo ' htmldocs (HTML), mandocs (man pages, use installmandocs to install)'
###
# Temporary files left by various tools
clean-files := $(DOCBOOKS) \
$(patsubst %.xml, %.dvi, $(DOCBOOKS)) \
$(patsubst %.xml, %.aux, $(DOCBOOKS)) \
$(patsubst %.xml, %.tex, $(DOCBOOKS)) \
$(patsubst %.xml, %.log, $(DOCBOOKS)) \
$(patsubst %.xml, %.out, $(DOCBOOKS)) \
$(patsubst %.xml, %.ps, $(DOCBOOKS)) \
$(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
$(patsubst %.xml, %.html, $(DOCBOOKS)) \
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
$(C-procfs-example)
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
#man put files in man subdir - traverse down
subdir- := man/

View File

@@ -0,0 +1,341 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="DoingIO">
<bookinfo>
<title>Bus-Independent Device Accesses</title>
<authorgroup>
<author>
<firstname>Matthew</firstname>
<surname>Wilcox</surname>
<affiliation>
<address>
<email>matthew@wil.cx</email>
</address>
</affiliation>
</author>
</authorgroup>
<authorgroup>
<author>
<firstname>Alan</firstname>
<surname>Cox</surname>
<affiliation>
<address>
<email>alan@redhat.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2001</year>
<holder>Matthew Wilcox</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
Linux provides an API which abstracts performing IO across all busses
and devices, allowing device drivers to be written independently of
bus type.
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
None.
</para>
</chapter>
<chapter id="mmio">
<title>Memory Mapped IO</title>
<sect1>
<title>Getting Access to the Device</title>
<para>
The most widely supported form of IO is memory mapped IO.
That is, a part of the CPU's address space is interpreted
not as accesses to memory, but as accesses to a device. Some
architectures define devices to be at a fixed address, but most
have some method of discovering devices. The PCI bus walk is a
good example of such a scheme. This document does not cover how
to receive such an address, but assumes you are starting with one.
Physical addresses are of type unsigned long.
</para>
<para>
This address should not be used directly. Instead, to get an
address suitable for passing to the accessor functions described
below, you should call <function>ioremap</function>.
An address suitable for accessing the device will be returned to you.
</para>
<para>
After you've finished using the device (say, in your module's
exit routine), call <function>iounmap</function> in order to return
the address space to the kernel. Most architectures allocate new
address space each time you call <function>ioremap</function>, and
they can run out unless you call <function>iounmap</function>.
</para>
</sect1>
<sect1>
<title>Accessing the device</title>
<para>
The part of the interface most used by drivers is reading and
writing memory-mapped registers on the device. Linux provides
interfaces to read and write 8-bit, 16-bit, 32-bit and 64-bit
quantities. Due to a historical accident, these are named byte,
word, long and quad accesses. Both read and write accesses are
supported; there is no prefetch support at this time.
</para>
<para>
The functions are named <function>readb</function>,
<function>readw</function>, <function>readl</function>,
<function>readq</function>, <function>readb_relaxed</function>,
<function>readw_relaxed</function>, <function>readl_relaxed</function>,
<function>readq_relaxed</function>, <function>writeb</function>,
<function>writew</function>, <function>writel</function> and
<function>writeq</function>.
</para>
<para>
Some devices (such as framebuffers) would like to use larger
transfers than 8 bytes at a time. For these devices, the
<function>memcpy_toio</function>, <function>memcpy_fromio</function>
and <function>memset_io</function> functions are provided.
Do not use memset or memcpy on IO addresses; they
are not guaranteed to copy data in order.
</para>
<para>
The read and write functions are defined to be ordered. That is the
compiler is not permitted to reorder the I/O sequence. When the
ordering can be compiler optimised, you can use <function>
__readb</function> and friends to indicate the relaxed ordering. Use
this with care.
</para>
<para>
While the basic functions are defined to be synchronous with respect
to each other and ordered with respect to each other the busses the
devices sit on may themselves have asynchronicity. In particular many
authors are burned by the fact that PCI bus writes are posted
asynchronously. A driver author must issue a read from the same
device to ensure that writes have occurred in the specific cases the
author cares. This kind of property cannot be hidden from driver
writers in the API. In some cases, the read used to flush the device
may be expected to fail (if the card is resetting, for example). In
that case, the read should be done from config space, which is
guaranteed to soft-fail if the card doesn't respond.
</para>
<para>
The following is an example of flushing a write to a device when
the driver would like to ensure the write's effects are visible prior
to continuing execution.
</para>
<programlisting>
static inline void
qla1280_disable_intrs(struct scsi_qla_host *ha)
{
struct device_reg *reg;
reg = ha->iobase;
/* disable risc and host interrupts */
WRT_REG_WORD(&amp;reg->ictrl, 0);
/*
* The following read will ensure that the above write
* has been received by the device before we return from this
* function.
*/
RD_REG_WORD(&amp;reg->ictrl);
ha->flags.ints_enabled = 0;
}
</programlisting>
<para>
In addition to write posting, on some large multiprocessing systems
(e.g. SGI Challenge, Origin and Altix machines) posted writes won't
be strongly ordered coming from different CPUs. Thus it's important
to properly protect parts of your driver that do memory-mapped writes
with locks and use the <function>mmiowb</function> to make sure they
arrive in the order intended. Issuing a regular <function>readX
</function> will also ensure write ordering, but should only be used
when the driver has to be sure that the write has actually arrived
at the device (not that it's simply ordered with respect to other
writes), since a full <function>readX</function> is a relatively
expensive operation.
</para>
<para>
Generally, one should use <function>mmiowb</function> prior to
releasing a spinlock that protects regions using <function>writeb
</function> or similar functions that aren't surrounded by <function>
readb</function> calls, which will ensure ordering and flushing. The
following pseudocode illustrates what might occur if write ordering
isn't guaranteed via <function>mmiowb</function> or one of the
<function>readX</function> functions.
</para>
<programlisting>
CPU A: spin_lock_irqsave(&amp;dev_lock, flags)
CPU A: ...
CPU A: writel(newval, ring_ptr);
CPU A: spin_unlock_irqrestore(&amp;dev_lock, flags)
...
CPU B: spin_lock_irqsave(&amp;dev_lock, flags)
CPU B: writel(newval2, ring_ptr);
CPU B: ...
CPU B: spin_unlock_irqrestore(&amp;dev_lock, flags)
</programlisting>
<para>
In the case above, newval2 could be written to ring_ptr before
newval. Fixing it is easy though:
</para>
<programlisting>
CPU A: spin_lock_irqsave(&amp;dev_lock, flags)
CPU A: ...
CPU A: writel(newval, ring_ptr);
CPU A: mmiowb(); /* ensure no other writes beat us to the device */
CPU A: spin_unlock_irqrestore(&amp;dev_lock, flags)
...
CPU B: spin_lock_irqsave(&amp;dev_lock, flags)
CPU B: writel(newval2, ring_ptr);
CPU B: ...
CPU B: mmiowb();
CPU B: spin_unlock_irqrestore(&amp;dev_lock, flags)
</programlisting>
<para>
See tg3.c for a real world example of how to use <function>mmiowb
</function>
</para>
<para>
PCI ordering rules also guarantee that PIO read responses arrive
after any outstanding DMA writes from that bus, since for some devices
the result of a <function>readb</function> call may signal to the
driver that a DMA transaction is complete. In many cases, however,
the driver may want to indicate that the next
<function>readb</function> call has no relation to any previous DMA
writes performed by the device. The driver can use
<function>readb_relaxed</function> for these cases, although only
some platforms will honor the relaxed semantics. Using the relaxed
read functions will provide significant performance benefits on
platforms that support it. The qla2xxx driver provides examples
of how to use <function>readX_relaxed</function>. In many cases,
a majority of the driver's <function>readX</function> calls can
safely be converted to <function>readX_relaxed</function> calls, since
only a few will indicate or depend on DMA completion.
</para>
</sect1>
<sect1>
<title>ISA legacy functions</title>
<para>
On older kernels (2.2 and earlier) the ISA bus could be read or
written with these functions and without ioremap being used. This is
no longer true in Linux 2.4. A set of equivalent functions exist for
easy legacy driver porting. The functions available are prefixed
with 'isa_' and are <function>isa_readb</function>,
<function>isa_writeb</function>, <function>isa_readw</function>,
<function>isa_writew</function>, <function>isa_readl</function>,
<function>isa_writel</function>, <function>isa_memcpy_fromio</function>
and <function>isa_memcpy_toio</function>
</para>
<para>
These functions should not be used in new drivers, and will
eventually be going away.
</para>
</sect1>
</chapter>
<chapter>
<title>Port Space Accesses</title>
<sect1>
<title>Port Space Explained</title>
<para>
Another form of IO commonly supported is Port Space. This is a
range of addresses separate to the normal memory address space.
Access to these addresses is generally not as fast as accesses
to the memory mapped addresses, and it also has a potentially
smaller address space.
</para>
<para>
Unlike memory mapped IO, no preparation is required
to access port space.
</para>
</sect1>
<sect1>
<title>Accessing Port Space</title>
<para>
Accesses to this space are provided through a set of functions
which allow 8-bit, 16-bit and 32-bit accesses; also
known as byte, word and long. These functions are
<function>inb</function>, <function>inw</function>,
<function>inl</function>, <function>outb</function>,
<function>outw</function> and <function>outl</function>.
</para>
<para>
Some variants are provided for these functions. Some devices
require that accesses to their ports are slowed down. This
functionality is provided by appending a <function>_p</function>
to the end of the function. There are also equivalents to memcpy.
The <function>ins</function> and <function>outs</function>
functions copy bytes, words or longs to the given port.
</para>
</sect1>
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Einclude/asm-i386/io.h
</chapter>
</book>

View File

@@ -0,0 +1,752 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="USB-Gadget-API">
<bookinfo>
<title>USB Gadget API for Linux</title>
<date>20 August 2004</date>
<edition>20 August 2004</edition>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
<copyright>
<year>2003-2004</year>
<holder>David Brownell</holder>
</copyright>
<author>
<firstname>David</firstname>
<surname>Brownell</surname>
<affiliation>
<address><email>dbrownell@users.sourceforge.net</email></address>
</affiliation>
</author>
</bookinfo>
<toc></toc>
<chapter><title>Introduction</title>
<para>This document presents a Linux-USB "Gadget"
kernel mode
API, for use within peripherals and other USB devices
that embed Linux.
It provides an overview of the API structure,
and shows how that fits into a system development project.
This is the first such API released on Linux to address
a number of important problems, including: </para>
<itemizedlist>
<listitem><para>Supports USB 2.0, for high speed devices which
can stream data at several dozen megabytes per second.
</para></listitem>
<listitem><para>Handles devices with dozens of endpoints just as
well as ones with just two fixed-function ones. Gadget drivers
can be written so they're easy to port to new hardware.
</para></listitem>
<listitem><para>Flexible enough to expose more complex USB device
capabilities such as multiple configurations, multiple interfaces,
composite devices,
and alternate interface settings.
</para></listitem>
<listitem><para>USB "On-The-Go" (OTG) support, in conjunction
with updates to the Linux-USB host side.
</para></listitem>
<listitem><para>Sharing data structures and API models with the
Linux-USB host side API. This helps the OTG support, and
looks forward to more-symmetric frameworks (where the same
I/O model is used by both host and device side drivers).
</para></listitem>
<listitem><para>Minimalist, so it's easier to support new device
controller hardware. I/O processing doesn't imply large
demands for memory or CPU resources.
</para></listitem>
</itemizedlist>
<para>Most Linux developers will not be able to use this API, since they
have USB "host" hardware in a PC, workstation, or server.
Linux users with embedded systems are more likely to
have USB peripheral hardware.
To distinguish drivers running inside such hardware from the
more familiar Linux "USB device drivers",
which are host side proxies for the real USB devices,
a different term is used:
the drivers inside the peripherals are "USB gadget drivers".
In USB protocol interactions, the device driver is the master
(or "client driver")
and the gadget driver is the slave (or "function driver").
</para>
<para>The gadget API resembles the host side Linux-USB API in that both
use queues of request objects to package I/O buffers, and those requests
may be submitted or canceled.
They share common definitions for the standard USB
<emphasis>Chapter 9</emphasis> messages, structures, and constants.
Also, both APIs bind and unbind drivers to devices.
The APIs differ in detail, since the host side's current
URB framework exposes a number of implementation details
and assumptions that are inappropriate for a gadget API.
While the model for control transfers and configuration
management is necessarily different (one side is a hardware-neutral master,
the other is a hardware-aware slave), the endpoint I/0 API used here
should also be usable for an overhead-reduced host side API.
</para>
</chapter>
<chapter id="structure"><title>Structure of Gadget Drivers</title>
<para>A system running inside a USB peripheral
normally has at least three layers inside the kernel to handle
USB protocol processing, and may have additional layers in
user space code.
The "gadget" API is used by the middle layer to interact
with the lowest level (which directly handles hardware).
</para>
<para>In Linux, from the bottom up, these layers are:
</para>
<variablelist>
<varlistentry>
<term><emphasis>USB Controller Driver</emphasis></term>
<listitem>
<para>This is the lowest software level.
It is the only layer that talks to hardware,
through registers, fifos, dma, irqs, and the like.
The <filename>&lt;linux/usb_gadget.h&gt;</filename> API abstracts
the peripheral controller endpoint hardware.
That hardware is exposed through endpoint objects, which accept
streams of IN/OUT buffers, and through callbacks that interact
with gadget drivers.
Since normal USB devices only have one upstream
port, they only have one of these drivers.
The controller driver can support any number of different
gadget drivers, but only one of them can be used at a time.
</para>
<para>Examples of such controller hardware include
the PCI-based NetChip 2280 USB 2.0 high speed controller,
the SA-11x0 or PXA-25x UDC (found within many PDAs),
and a variety of other products.
</para>
</listitem></varlistentry>
<varlistentry>
<term><emphasis>Gadget Driver</emphasis></term>
<listitem>
<para>The lower boundary of this driver implements hardware-neutral
USB functions, using calls to the controller driver.
Because such hardware varies widely in capabilities and restrictions,
and is used in embedded environments where space is at a premium,
the gadget driver is often configured at compile time
to work with endpoints supported by one particular controller.
Gadget drivers may be portable to several different controllers,
using conditional compilation.
(Recent kernels substantially simplify the work involved in
supporting new hardware, by <emphasis>autoconfiguring</emphasis>
endpoints automatically for many bulk-oriented drivers.)
Gadget driver responsibilities include:
</para>
<itemizedlist>
<listitem><para>handling setup requests (ep0 protocol responses)
possibly including class-specific functionality
</para></listitem>
<listitem><para>returning configuration and string descriptors
</para></listitem>
<listitem><para>(re)setting configurations and interface
altsettings, including enabling and configuring endpoints
</para></listitem>
<listitem><para>handling life cycle events, such as managing
bindings to hardware,
USB suspend/resume, remote wakeup,
and disconnection from the USB host.
</para></listitem>
<listitem><para>managing IN and OUT transfers on all currently
enabled endpoints
</para></listitem>
</itemizedlist>
<para>
Such drivers may be modules of proprietary code, although
that approach is discouraged in the Linux community.
</para>
</listitem></varlistentry>
<varlistentry>
<term><emphasis>Upper Level</emphasis></term>
<listitem>
<para>Most gadget drivers have an upper boundary that connects
to some Linux driver or framework in Linux.
Through that boundary flows the data which the gadget driver
produces and/or consumes through protocol transfers over USB.
Examples include:
</para>
<itemizedlist>
<listitem><para>user mode code, using generic (gadgetfs)
or application specific files in
<filename>/dev</filename>
</para></listitem>
<listitem><para>networking subsystem (for network gadgets,
like the CDC Ethernet Model gadget driver)
</para></listitem>
<listitem><para>data capture drivers, perhaps video4Linux or
a scanner driver; or test and measurement hardware.
</para></listitem>
<listitem><para>input subsystem (for HID gadgets)
</para></listitem>
<listitem><para>sound subsystem (for audio gadgets)
</para></listitem>
<listitem><para>file system (for PTP gadgets)
</para></listitem>
<listitem><para>block i/o subsystem (for usb-storage gadgets)
</para></listitem>
<listitem><para>... and more </para></listitem>
</itemizedlist>
</listitem></varlistentry>
<varlistentry>
<term><emphasis>Additional Layers</emphasis></term>
<listitem>
<para>Other layers may exist.
These could include kernel layers, such as network protocol stacks,
as well as user mode applications building on standard POSIX
system call APIs such as
<emphasis>open()</emphasis>, <emphasis>close()</emphasis>,
<emphasis>read()</emphasis> and <emphasis>write()</emphasis>.
On newer systems, POSIX Async I/O calls may be an option.
Such user mode code will not necessarily be subject to
the GNU General Public License (GPL).
</para>
</listitem></varlistentry>
</variablelist>
<para>OTG-capable systems will also need to include a standard Linux-USB
host side stack,
with <emphasis>usbcore</emphasis>,
one or more <emphasis>Host Controller Drivers</emphasis> (HCDs),
<emphasis>USB Device Drivers</emphasis> to support
the OTG "Targeted Peripheral List",
and so forth.
There will also be an <emphasis>OTG Controller Driver</emphasis>,
which is visible to gadget and device driver developers only indirectly.
That helps the host and device side USB controllers implement the
two new OTG protocols (HNP and SRP).
Roles switch (host to peripheral, or vice versa) using HNP
during USB suspend processing, and SRP can be viewed as a
more battery-friendly kind of device wakeup protocol.
</para>
<para>Over time, reusable utilities are evolving to help make some
gadget driver tasks simpler.
For example, building configuration descriptors from vectors of
descriptors for the configurations interfaces and endpoints is
now automated, and many drivers now use autoconfiguration to
choose hardware endpoints and initialize their descriptors.
A potential example of particular interest
is code implementing standard USB-IF protocols for
HID, networking, storage, or audio classes.
Some developers are interested in KDB or KGDB hooks, to let
target hardware be remotely debugged.
Most such USB protocol code doesn't need to be hardware-specific,
any more than network protocols like X11, HTTP, or NFS are.
Such gadget-side interface drivers should eventually be combined,
to implement composite devices.
</para>
</chapter>
<chapter id="api"><title>Kernel Mode Gadget API</title>
<para>Gadget drivers declare themselves through a
<emphasis>struct usb_gadget_driver</emphasis>, which is responsible for
most parts of enumeration for a <emphasis>struct usb_gadget</emphasis>.
The response to a set_configuration usually involves
enabling one or more of the <emphasis>struct usb_ep</emphasis> objects
exposed by the gadget, and submitting one or more
<emphasis>struct usb_request</emphasis> buffers to transfer data.
Understand those four data types, and their operations, and
you will understand how this API works.
</para>
<note><title>Incomplete Data Type Descriptions</title>
<para>This documentation was prepared using the standard Linux
kernel <filename>docproc</filename> tool, which turns text
and in-code comments into SGML DocBook and then into usable
formats such as HTML or PDF.
Other than the "Chapter 9" data types, most of the significant
data types and functions are described here.
</para>
<para>However, docproc does not understand all the C constructs
that are used, so some relevant information is likely omitted from
what you are reading.
One example of such information is endpoint autoconfiguration.
You'll have to read the header file, and use example source
code (such as that for "Gadget Zero"), to fully understand the API.
</para>
<para>The part of the API implementing some basic
driver capabilities is specific to the version of the
Linux kernel that's in use.
The 2.6 kernel includes a <emphasis>driver model</emphasis>
framework that has no analogue on earlier kernels;
so those parts of the gadget API are not fully portable.
(They are implemented on 2.4 kernels, but in a different way.)
The driver model state is another part of this API that is
ignored by the kerneldoc tools.
</para>
</note>
<para>The core API does not expose
every possible hardware feature, only the most widely available ones.
There are significant hardware features, such as device-to-device DMA
(without temporary storage in a memory buffer)
that would be added using hardware-specific APIs.
</para>
<para>This API allows drivers to use conditional compilation to handle
endpoint capabilities of different hardware, but doesn't require that.
Hardware tends to have arbitrary restrictions, relating to
transfer types, addressing, packet sizes, buffering, and availability.
As a rule, such differences only matter for "endpoint zero" logic
that handles device configuration and management.
The API supports limited run-time
detection of capabilities, through naming conventions for endpoints.
Many drivers will be able to at least partially autoconfigure
themselves.
In particular, driver init sections will often have endpoint
autoconfiguration logic that scans the hardware's list of endpoints
to find ones matching the driver requirements
(relying on those conventions), to eliminate some of the most
common reasons for conditional compilation.
</para>
<para>Like the Linux-USB host side API, this API exposes
the "chunky" nature of USB messages: I/O requests are in terms
of one or more "packets", and packet boundaries are visible to drivers.
Compared to RS-232 serial protocols, USB resembles
synchronous protocols like HDLC
(N bytes per frame, multipoint addressing, host as the primary
station and devices as secondary stations)
more than asynchronous ones
(tty style: 8 data bits per frame, no parity, one stop bit).
So for example the controller drivers won't buffer
two single byte writes into a single two-byte USB IN packet,
although gadget drivers may do so when they implement
protocols where packet boundaries (and "short packets")
are not significant.
</para>
<sect1 id="lifecycle"><title>Driver Life Cycle</title>
<para>Gadget drivers make endpoint I/O requests to hardware without
needing to know many details of the hardware, but driver
setup/configuration code needs to handle some differences.
Use the API like this:
</para>
<orderedlist numeration='arabic'>
<listitem><para>Register a driver for the particular device side
usb controller hardware,
such as the net2280 on PCI (USB 2.0),
sa11x0 or pxa25x as found in Linux PDAs,
and so on.
At this point the device is logically in the USB ch9 initial state
("attached"), drawing no power and not usable
(since it does not yet support enumeration).
Any host should not see the device, since it's not
activated the data line pullup used by the host to
detect a device, even if VBUS power is available.
</para></listitem>
<listitem><para>Register a gadget driver that implements some higher level
device function. That will then bind() to a usb_gadget, which
activates the data line pullup sometime after detecting VBUS.
</para></listitem>
<listitem><para>The hardware driver can now start enumerating.
The steps it handles are to accept USB power and set_address requests.
Other steps are handled by the gadget driver.
If the gadget driver module is unloaded before the host starts to
enumerate, steps before step 7 are skipped.
</para></listitem>
<listitem><para>The gadget driver's setup() call returns usb descriptors,
based both on what the bus interface hardware provides and on the
functionality being implemented.
That can involve alternate settings or configurations,
unless the hardware prevents such operation.
For OTG devices, each configuration descriptor includes
an OTG descriptor.
</para></listitem>
<listitem><para>The gadget driver handles the last step of enumeration,
when the USB host issues a set_configuration call.
It enables all endpoints used in that configuration,
with all interfaces in their default settings.
That involves using a list of the hardware's endpoints, enabling each
endpoint according to its descriptor.
It may also involve using <function>usb_gadget_vbus_draw</function>
to let more power be drawn from VBUS, as allowed by that configuration.
For OTG devices, setting a configuration may also involve reporting
HNP capabilities through a user interface.
</para></listitem>
<listitem><para>Do real work and perform data transfers, possibly involving
changes to interface settings or switching to new configurations, until the
device is disconnect()ed from the host.
Queue any number of transfer requests to each endpoint.
It may be suspended and resumed several times before being disconnected.
On disconnect, the drivers go back to step 3 (above).
</para></listitem>
<listitem><para>When the gadget driver module is being unloaded,
the driver unbind() callback is issued. That lets the controller
driver be unloaded.
</para></listitem>
</orderedlist>
<para>Drivers will normally be arranged so that just loading the
gadget driver module (or statically linking it into a Linux kernel)
allows the peripheral device to be enumerated, but some drivers
will defer enumeration until some higher level component (like
a user mode daemon) enables it.
Note that at this lowest level there are no policies about how
ep0 configuration logic is implemented,
except that it should obey USB specifications.
Such issues are in the domain of gadget drivers,
including knowing about implementation constraints
imposed by some USB controllers
or understanding that composite devices might happen to
be built by integrating reusable components.
</para>
<para>Note that the lifecycle above can be slightly different
for OTG devices.
Other than providing an additional OTG descriptor in each
configuration, only the HNP-related differences are particularly
visible to driver code.
They involve reporting requirements during the SET_CONFIGURATION
request, and the option to invoke HNP during some suspend callbacks.
Also, SRP changes the semantics of
<function>usb_gadget_wakeup</function>
slightly.
</para>
</sect1>
<sect1 id="ch9"><title>USB 2.0 Chapter 9 Types and Constants</title>
<para>Gadget drivers
rely on common USB structures and constants
defined in the
<filename>&lt;linux/usb_ch9.h&gt;</filename>
header file, which is standard in Linux 2.6 kernels.
These are the same types and constants used by host
side drivers (and usbcore).
</para>
!Iinclude/linux/usb_ch9.h
</sect1>
<sect1 id="core"><title>Core Objects and Methods</title>
<para>These are declared in
<filename>&lt;linux/usb_gadget.h&gt;</filename>,
and are used by gadget drivers to interact with
USB peripheral controller drivers.
</para>
<!-- yeech, this is ugly in nsgmls PDF output.
the PDF bookmark and refentry output nesting is wrong,
and the member/argument documentation indents ugly.
plus something (docproc?) adds whitespace before the
descriptive paragraph text, so it can't line up right
unless the explanations are trivial.
-->
!Iinclude/linux/usb_gadget.h
</sect1>
<sect1 id="utils"><title>Optional Utilities</title>
<para>The core API is sufficient for writing a USB Gadget Driver,
but some optional utilities are provided to simplify common tasks.
These utilities include endpoint autoconfiguration.
</para>
!Edrivers/usb/gadget/usbstring.c
!Edrivers/usb/gadget/config.c
<!-- !Edrivers/usb/gadget/epautoconf.c -->
</sect1>
</chapter>
<chapter id="controllers"><title>Peripheral Controller Drivers</title>
<para>The first hardware supporting this API was the NetChip 2280
controller, which supports USB 2.0 high speed and is based on PCI.
This is the <filename>net2280</filename> driver module.
The driver supports Linux kernel versions 2.4 and 2.6;
contact NetChip Technologies for development boards and product
information.
</para>
<para>Other hardware working in the "gadget" framework includes:
Intel's PXA 25x and IXP42x series processors
(<filename>pxa2xx_udc</filename>),
Toshiba TC86c001 "Goku-S" (<filename>goku_udc</filename>),
Renesas SH7705/7727 (<filename>sh_udc</filename>),
MediaQ 11xx (<filename>mq11xx_udc</filename>),
Hynix HMS30C7202 (<filename>h7202_udc</filename>),
National 9303/4 (<filename>n9604_udc</filename>),
Texas Instruments OMAP (<filename>omap_udc</filename>),
Sharp LH7A40x (<filename>lh7a40x_udc</filename>),
and more.
Most of those are full speed controllers.
</para>
<para>At this writing, there are people at work on drivers in
this framework for several other USB device controllers,
with plans to make many of them be widely available.
</para>
<!-- !Edrivers/usb/gadget/net2280.c -->
<para>A partial USB simulator,
the <filename>dummy_hcd</filename> driver, is available.
It can act like a net2280, a pxa25x, or an sa11x0 in terms
of available endpoints and device speeds; and it simulates
control, bulk, and to some extent interrupt transfers.
That lets you develop some parts of a gadget driver on a normal PC,
without any special hardware, and perhaps with the assistance
of tools such as GDB running with User Mode Linux.
At least one person has expressed interest in adapting that
approach, hooking it up to a simulator for a microcontroller.
Such simulators can help debug subsystems where the runtime hardware
is unfriendly to software development, or is not yet available.
</para>
<para>Support for other controllers is expected to be developed
and contributed
over time, as this driver framework evolves.
</para>
</chapter>
<chapter id="gadget"><title>Gadget Drivers</title>
<para>In addition to <emphasis>Gadget Zero</emphasis>
(used primarily for testing and development with drivers
for usb controller hardware), other gadget drivers exist.
</para>
<para>There's an <emphasis>ethernet</emphasis> gadget
driver, which implements one of the most useful
<emphasis>Communications Device Class</emphasis> (CDC) models.
One of the standards for cable modem interoperability even
specifies the use of this ethernet model as one of two
mandatory options.
Gadgets using this code look to a USB host as if they're
an Ethernet adapter.
It provides access to a network where the gadget's CPU is one host,
which could easily be bridging, routing, or firewalling
access to other networks.
Since some hardware can't fully implement the CDC Ethernet
requirements, this driver also implements a "good parts only"
subset of CDC Ethernet.
(That subset doesn't advertise itself as CDC Ethernet,
to avoid creating problems.)
</para>
<para>Support for Microsoft's <emphasis>RNDIS</emphasis>
protocol has been contributed by Pengutronix and Auerswald GmbH.
This is like CDC Ethernet, but it runs on more slightly USB hardware
(but less than the CDC subset).
However, its main claim to fame is being able to connect directly to
recent versions of Windows, using drivers that Microsoft bundles
and supports, making it much simpler to network with Windows.
</para>
<para>There is also support for user mode gadget drivers,
using <emphasis>gadgetfs</emphasis>.
This provides a <emphasis>User Mode API</emphasis> that presents
each endpoint as a single file descriptor. I/O is done using
normal <emphasis>read()</emphasis> and <emphasis>read()</emphasis> calls.
Familiar tools like GDB and pthreads can be used to
develop and debug user mode drivers, so that once a robust
controller driver is available many applications for it
won't require new kernel mode software.
Linux 2.6 <emphasis>Async I/O (AIO)</emphasis>
support is available, so that user mode software
can stream data with only slightly more overhead
than a kernel driver.
</para>
<para>There's a USB Mass Storage class driver, which provides
a different solution for interoperability with systems such
as MS-Windows and MacOS.
That <emphasis>File-backed Storage</emphasis> driver uses a
file or block device as backing store for a drive,
like the <filename>loop</filename> driver.
The USB host uses the BBB, CB, or CBI versions of the mass
storage class specification, using transparent SCSI commands
to access the data from the backing store.
</para>
<para>There's a "serial line" driver, useful for TTY style
operation over USB.
The latest version of that driver supports CDC ACM style
operation, like a USB modem, and so on most hardware it can
interoperate easily with MS-Windows.
One interesting use of that driver is in boot firmware (like a BIOS),
which can sometimes use that model with very small systems without
real serial lines.
</para>
<para>Support for other kinds of gadget is expected to
be developed and contributed
over time, as this driver framework evolves.
</para>
</chapter>
<chapter id="otg"><title>USB On-The-GO (OTG)</title>
<para>USB OTG support on Linux 2.6 was initially developed
by Texas Instruments for
<ulink url="http://www.omap.com">OMAP</ulink> 16xx and 17xx
series processors.
Other OTG systems should work in similar ways, but the
hardware level details could be very different.
</para>
<para>Systems need specialized hardware support to implement OTG,
notably including a special <emphasis>Mini-AB</emphasis> jack
and associated transciever to support <emphasis>Dual-Role</emphasis>
operation:
they can act either as a host, using the standard
Linux-USB host side driver stack,
or as a peripheral, using this "gadget" framework.
To do that, the system software relies on small additions
to those programming interfaces,
and on a new internal component (here called an "OTG Controller")
affecting which driver stack connects to the OTG port.
In each role, the system can re-use the existing pool of
hardware-neutral drivers, layered on top of the controller
driver interfaces (<emphasis>usb_bus</emphasis> or
<emphasis>usb_gadget</emphasis>).
Such drivers need at most minor changes, and most of the calls
added to support OTG can also benefit non-OTG products.
</para>
<itemizedlist>
<listitem><para>Gadget drivers test the <emphasis>is_otg</emphasis>
flag, and use it to determine whether or not to include
an OTG descriptor in each of their configurations.
</para></listitem>
<listitem><para>Gadget drivers may need changes to support the
two new OTG protocols, exposed in new gadget attributes
such as <emphasis>b_hnp_enable</emphasis> flag.
HNP support should be reported through a user interface
(two LEDs could suffice), and is triggered in some cases
when the host suspends the peripheral.
SRP support can be user-initiated just like remote wakeup,
probably by pressing the same button.
</para></listitem>
<listitem><para>On the host side, USB device drivers need
to be taught to trigger HNP at appropriate moments, using
<function>usb_suspend_device()</function>.
That also conserves battery power, which is useful even
for non-OTG configurations.
</para></listitem>
<listitem><para>Also on the host side, a driver must support the
OTG "Targeted Peripheral List". That's just a whitelist,
used to reject peripherals not supported with a given
Linux OTG host.
<emphasis>This whitelist is product-specific;
each product must modify <filename>otg_whitelist.h</filename>
to match its interoperability specification.
</emphasis>
</para>
<para>Non-OTG Linux hosts, like PCs and workstations,
normally have some solution for adding drivers, so that
peripherals that aren't recognized can eventually be supported.
That approach is unreasonable for consumer products that may
never have their firmware upgraded, and where it's usually
unrealistic to expect traditional PC/workstation/server kinds
of support model to work.
For example, it's often impractical to change device firmware
once the product has been distributed, so driver bugs can't
normally be fixed if they're found after shipment.
</para></listitem>
</itemizedlist>
<para>
Additional changes are needed below those hardware-neutral
<emphasis>usb_bus</emphasis> and <emphasis>usb_gadget</emphasis>
driver interfaces; those aren't discussed here in any detail.
Those affect the hardware-specific code for each USB Host or Peripheral
controller, and how the HCD initializes (since OTG can be active only
on a single port).
They also involve what may be called an <emphasis>OTG Controller
Driver</emphasis>, managing the OTG transceiver and the OTG state
machine logic as well as much of the root hub behavior for the
OTG port.
The OTG controller driver needs to activate and deactivate USB
controllers depending on the relevant device role.
Some related changes were needed inside usbcore, so that it
can identify OTG-capable devices and respond appropriately
to HNP or SRP protocols.
</para>
</chapter>
</book>
<!--
vim:syntax=sgml:sw=4
-->

View File

@@ -0,0 +1,333 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="LinuxJBDAPI">
<bookinfo>
<title>The Linux Journalling API</title>
<authorgroup>
<author>
<firstname>Roger</firstname>
<surname>Gammans</surname>
<affiliation>
<address>
<email>rgammans@computer-surgery.co.uk</email>
</address>
</affiliation>
</author>
</authorgroup>
<authorgroup>
<author>
<firstname>Stephen</firstname>
<surname>Tweedie</surname>
<affiliation>
<address>
<email>sct@redhat.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2002</year>
<holder>Roger Gammans</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="Overview">
<title>Overview</title>
<sect1>
<title>Details</title>
<para>
The journalling layer is easy to use. You need to
first of all create a journal_t data structure. There are
two calls to do this dependent on how you decide to allocate the physical
media on which the journal resides. The journal_init_inode() call
is for journals stored in filesystem inodes, or the journal_init_dev()
call can be use for journal stored on a raw device (in a continuous range
of blocks). A journal_t is a typedef for a struct pointer, so when
you are finally finished make sure you call journal_destroy() on it
to free up any used kernel memory.
</para>
<para>
Once you have got your journal_t object you need to 'mount' or load the journal
file, unless of course you haven't initialised it yet - in which case you
need to call journal_create().
</para>
<para>
Most of the time however your journal file will already have been created, but
before you load it you must call journal_wipe() to empty the journal file.
Hang on, you say , what if the filesystem wasn't cleanly umount()'d . Well, it is the
job of the client file system to detect this and skip the call to journal_wipe().
</para>
<para>
In either case the next call should be to journal_load() which prepares the
journal file for use. Note that journal_wipe(..,0) calls journal_skip_recovery()
for you if it detects any outstanding transactions in the journal and similarly
journal_load() will call journal_recover() if necessary.
I would advise reading fs/ext3/super.c for examples on this stage.
[RGG: Why is the journal_wipe() call necessary - doesn't this needlessly
complicate the API. Or isn't a good idea for the journal layer to hide
dirty mounts from the client fs]
</para>
<para>
Now you can go ahead and start modifying the underlying
filesystem. Almost.
</para>
<para>
You still need to actually journal your filesystem changes, this
is done by wrapping them into transactions. Additionally you
also need to wrap the modification of each of the the buffers
with calls to the journal layer, so it knows what the modifications
you are actually making are. To do this use journal_start() which
returns a transaction handle.
</para>
<para>
journal_start()
and its counterpart journal_stop(), which indicates the end of a transaction
are nestable calls, so you can reenter a transaction if necessary,
but remember you must call journal_stop() the same number of times as
journal_start() before the transaction is completed (or more accurately
leaves the the update phase). Ext3/VFS makes use of this feature to simplify
quota support.
</para>
<para>
Inside each transaction you need to wrap the modifications to the
individual buffers (blocks). Before you start to modify a buffer you
need to call journal_get_{create,write,undo}_access() as appropriate,
this allows the journalling layer to copy the unmodified data if it
needs to. After all the buffer may be part of a previously uncommitted
transaction.
At this point you are at last ready to modify a buffer, and once
you are have done so you need to call journal_dirty_{meta,}data().
Or if you've asked for access to a buffer you now know is now longer
required to be pushed back on the device you can call journal_forget()
in much the same way as you might have used bforget() in the past.
</para>
<para>
A journal_flush() may be called at any time to commit and checkpoint
all your transactions.
</para>
<para>
Then at umount time , in your put_super() (2.4) or write_super() (2.5)
you can then call journal_destroy() to clean up your in-core journal object.
</para>
<para>
Unfortunately there a couple of ways the journal layer can cause a deadlock.
The first thing to note is that each task can only have
a single outstanding transaction at any one time, remember nothing
commits until the outermost journal_stop(). This means
you must complete the transaction at the end of each file/inode/address
etc. operation you perform, so that the journalling system isn't re-entered
on another journal. Since transactions can't be nested/batched
across differing journals, and another filesystem other than
yours (say ext3) may be modified in a later syscall.
</para>
<para>
The second case to bear in mind is that journal_start() can
block if there isn't enough space in the journal for your transaction
(based on the passed nblocks param) - when it blocks it merely(!) needs to
wait for transactions to complete and be committed from other tasks,
so essentially we are waiting for journal_stop(). So to avoid
deadlocks you must treat journal_start/stop() as if they
were semaphores and include them in your semaphore ordering rules to prevent
deadlocks. Note that journal_extend() has similar blocking behaviour to
journal_start() so you can deadlock here just as easily as on journal_start().
</para>
<para>
Try to reserve the right number of blocks the first time. ;-). This will
be the maximum number of blocks you are going to touch in this transaction.
I advise having a look at at least ext3_jbd.h to see the basis on which
ext3 uses to make these decisions.
</para>
<para>
Another wriggle to watch out for is your on-disk block allocation strategy.
why? Because, if you undo a delete, you need to ensure you haven't reused any
of the freed blocks in a later transaction. One simple way of doing this
is make sure any blocks you allocate only have checkpointed transactions
listed against them. Ext3 does this in ext3_test_allocatable().
</para>
<para>
Lock is also providing through journal_{un,}lock_updates(),
ext3 uses this when it wants a window with a clean and stable fs for a moment.
eg.
</para>
<programlisting>
journal_lock_updates() //stop new stuff happening..
journal_flush() // checkpoint everything.
..do stuff on stable fs
journal_unlock_updates() // carry on with filesystem use.
</programlisting>
<para>
The opportunities for abuse and DOS attacks with this should be obvious,
if you allow unprivileged userspace to trigger codepaths containing these
calls.
</para>
<para>
A new feature of jbd since 2.5.25 is commit callbacks with the new
journal_callback_set() function you can now ask the journalling layer
to call you back when the transaction is finally committed to disk, so that
you can do some of your own management. The key to this is the journal_callback
struct, this maintains the internal callback information but you can
extend it like this:-
</para>
<programlisting>
struct myfs_callback_s {
//Data structure element required by jbd..
struct journal_callback for_jbd;
// Stuff for myfs allocated together.
myfs_inode* i_commited;
}
</programlisting>
<para>
this would be useful if you needed to know when data was committed to a
particular inode.
</para>
</sect1>
<sect1>
<title>Summary</title>
<para>
Using the journal is a matter of wrapping the different context changes,
being each mount, each modification (transaction) and each changed buffer
to tell the journalling layer about them.
</para>
<para>
Here is a some pseudo code to give you an idea of how it works, as
an example.
</para>
<programlisting>
journal_t* my_jnrl = journal_create();
journal_init_{dev,inode}(jnrl,...)
if (clean) journal_wipe();
journal_load();
foreach(transaction) { /*transactions must be
completed before
a syscall returns to
userspace*/
handle_t * xct=journal_start(my_jnrl);
foreach(bh) {
journal_get_{create,write,undo}_access(xact,bh);
if ( myfs_modify(bh) ) { /* returns true
if makes changes */
journal_dirty_{meta,}data(xact,bh);
} else {
journal_forget(bh);
}
}
journal_stop(xct);
}
journal_destroy(my_jrnl);
</programlisting>
</sect1>
</chapter>
<chapter id="adt">
<title>Data Types</title>
<para>
The journalling layer uses typedefs to 'hide' the concrete definitions
of the structures used. As a client of the JBD layer you can
just rely on the using the pointer as a magic cookie of some sort.
Obviously the hiding is not enforced as this is 'C'.
</para>
<sect1><title>Structures</title>
!Iinclude/linux/jbd.h
</sect1>
</chapter>
<chapter id="calls">
<title>Functions</title>
<para>
The functions here are split into two groups those that
affect a journal as a whole, and those which are used to
manage transactions
</para>
<sect1><title>Journal Level</title>
!Efs/jbd/journal.c
!Efs/jbd/recovery.c
</sect1>
<sect1><title>Transasction Level</title>
!Efs/jbd/transaction.c
</sect1>
</chapter>
<chapter>
<title>See also</title>
<para>
<citation>
<ulink url="ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/journal-design.ps.gz">
Journaling the Linux ext2fs Filesystem,LinuxExpo 98, Stephen Tweedie
</ulink>
</citation>
</para>
<para>
<citation>
<ulink url="http://olstrans.sourceforge.net/release/OLS2000-ext3/OLS2000-ext3.html">
Ext3 Journalling FileSystem , OLS 2000, Dr. Stephen Tweedie
</ulink>
</citation>
</para>
</chapter>
</book>

View File

@@ -0,0 +1,342 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="LinuxKernelAPI">
<bookinfo>
<title>The Linux Kernel API</title>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="Basics">
<title>Driver Basics</title>
<sect1><title>Driver Entry and Exit points</title>
!Iinclude/linux/init.h
</sect1>
<sect1><title>Atomic and pointer manipulation</title>
!Iinclude/asm-i386/atomic.h
!Iinclude/asm-i386/unaligned.h
</sect1>
<!-- FIXME:
kernel/sched.c has no docs, which stuffs up the sgml. Comment
out until somebody adds docs. KAO
<sect1><title>Delaying, scheduling, and timer routines</title>
X!Ekernel/sched.c
</sect1>
KAO -->
</chapter>
<chapter id="adt">
<title>Data Types</title>
<sect1><title>Doubly Linked Lists</title>
!Iinclude/linux/list.h
</sect1>
</chapter>
<chapter id="libc">
<title>Basic C Library Functions</title>
<para>
When writing drivers, you cannot in general use routines which are
from the C Library. Some of the functions have been found generally
useful and they are listed below. The behaviour of these functions
may vary slightly from those defined by ANSI, and these deviations
are noted in the text.
</para>
<sect1><title>String Conversions</title>
!Ilib/vsprintf.c
!Elib/vsprintf.c
</sect1>
<sect1><title>String Manipulation</title>
!Ilib/string.c
!Elib/string.c
</sect1>
<sect1><title>Bit Operations</title>
!Iinclude/asm-i386/bitops.h
</sect1>
</chapter>
<chapter id="mm">
<title>Memory Management in Linux</title>
<sect1><title>The Slab Cache</title>
!Emm/slab.c
</sect1>
<sect1><title>User Space Memory Access</title>
!Iinclude/asm-i386/uaccess.h
!Iarch/i386/lib/usercopy.c
</sect1>
</chapter>
<chapter id="kfifo">
<title>FIFO Buffer</title>
<sect1><title>kfifo interface</title>
!Iinclude/linux/kfifo.h
!Ekernel/kfifo.c
</sect1>
</chapter>
<chapter id="proc">
<title>The proc filesystem</title>
<sect1><title>sysctl interface</title>
!Ekernel/sysctl.c
</sect1>
</chapter>
<chapter id="debugfs">
<title>The debugfs filesystem</title>
<sect1><title>debugfs interface</title>
!Efs/debugfs/inode.c
!Efs/debugfs/file.c
</sect1>
</chapter>
<chapter id="vfs">
<title>The Linux VFS</title>
<sect1><title>The Directory Cache</title>
!Efs/dcache.c
!Iinclude/linux/dcache.h
</sect1>
<sect1><title>Inode Handling</title>
!Efs/inode.c
!Efs/bad_inode.c
</sect1>
<sect1><title>Registration and Superblocks</title>
!Efs/super.c
</sect1>
<sect1><title>File Locks</title>
!Efs/locks.c
!Ifs/locks.c
</sect1>
</chapter>
<chapter id="netcore">
<title>Linux Networking</title>
<sect1><title>Socket Buffer Functions</title>
!Iinclude/linux/skbuff.h
!Enet/core/skbuff.c
</sect1>
<sect1><title>Socket Filter</title>
!Enet/core/filter.c
</sect1>
<sect1><title>Generic Network Statistics</title>
!Iinclude/linux/gen_stats.h
!Enet/core/gen_stats.c
!Enet/core/gen_estimator.c
</sect1>
</chapter>
<chapter id="netdev">
<title>Network device support</title>
<sect1><title>Driver Support</title>
!Enet/core/dev.c
</sect1>
<sect1><title>8390 Based Network Cards</title>
!Edrivers/net/8390.c
</sect1>
<sect1><title>Synchronous PPP</title>
!Edrivers/net/wan/syncppp.c
</sect1>
</chapter>
<chapter id="modload">
<title>Module Support</title>
<sect1><title>Module Loading</title>
!Ekernel/kmod.c
</sect1>
<sect1><title>Inter Module support</title>
<para>
Refer to the file kernel/module.c for more information.
</para>
<!-- FIXME: Removed for now since no structured comments in source
X!Ekernel/module.c
-->
</sect1>
</chapter>
<chapter id="hardware">
<title>Hardware Interfaces</title>
<sect1><title>Interrupt Handling</title>
!Iarch/i386/kernel/irq.c
</sect1>
<sect1><title>MTRR Handling</title>
!Earch/i386/kernel/cpu/mtrr/main.c
</sect1>
<sect1><title>PCI Support Library</title>
!Edrivers/pci/pci.c
</sect1>
<sect1><title>PCI Hotplug Support Library</title>
!Edrivers/pci/hotplug/pci_hotplug_core.c
</sect1>
<sect1><title>MCA Architecture</title>
<sect2><title>MCA Device Functions</title>
<para>
Refer to the file arch/i386/kernel/mca.c for more information.
</para>
<!-- FIXME: Removed for now since no structured comments in source
X!Earch/i386/kernel/mca.c
-->
</sect2>
<sect2><title>MCA Bus DMA</title>
!Iinclude/asm-i386/mca_dma.h
</sect2>
</sect1>
</chapter>
<chapter id="devfs">
<title>The Device File System</title>
!Efs/devfs/base.c
</chapter>
<chapter id="security">
<title>Security Framework</title>
!Esecurity/security.c
</chapter>
<chapter id="pmfuncs">
<title>Power Management</title>
!Ekernel/power/pm.c
</chapter>
<chapter id="blkdev">
<title>Block Devices</title>
!Edrivers/block/ll_rw_blk.c
</chapter>
<chapter id="miscdev">
<title>Miscellaneous Devices</title>
!Edrivers/char/misc.c
</chapter>
<chapter id="viddev">
<title>Video4Linux</title>
!Edrivers/media/video/videodev.c
</chapter>
<chapter id="snddev">
<title>Sound Devices</title>
!Esound/sound_core.c
<!-- FIXME: Removed for now since no structured comments in source
X!Isound/sound_firmware.c
-->
</chapter>
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
!Edrivers/serial/serial_core.c
!Edrivers/serial/8250.c
</chapter>
<chapter id="z85230">
<title>Z85230 Support Library</title>
!Edrivers/net/wan/z85230.c
</chapter>
<chapter id="fbdev">
<title>Frame Buffer Library</title>
<para>
The frame buffer drivers depend heavily on four data structures.
These structures are declared in include/linux/fb.h. They are
fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs.
The last three can be made available to and from userland.
</para>
<para>
fb_info defines the current state of a particular video card.
Inside fb_info, there exists a fb_ops structure which is a
collection of needed functions to make fbdev and fbcon work.
fb_info is only visible to the kernel.
</para>
<para>
fb_var_screeninfo is used to describe the features of a video card
that are user defined. With fb_var_screeninfo, things such as
depth and the resolution may be defined.
</para>
<para>
The next structure is fb_fix_screeninfo. This defines the
properties of a card that are created when a mode is set and can't
be changed otherwise. A good example of this is the start of the
frame buffer memory. This "locks" the address of the frame buffer
memory, so that it cannot be changed or moved.
</para>
<para>
The last structure is fb_monospecs. In the old API, there was
little importance for fb_monospecs. This allowed for forbidden things
such as setting a mode of 800x600 on a fix frequency monitor. With
the new API, fb_monospecs prevents such things, and if used
correctly, can prevent a monitor from being cooked. fb_monospecs
will not be useful until kernels 2.5.x.
</para>
<sect1><title>Frame Buffer Memory</title>
!Edrivers/video/fbmem.c
</sect1>
<sect1><title>Frame Buffer Console</title>
!Edrivers/video/console/fbcon.c
</sect1>
<sect1><title>Frame Buffer Colormap</title>
!Edrivers/video/fbcmap.c
</sect1>
<!-- FIXME:
drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment
out until somebody adds docs. KAO
<sect1><title>Frame Buffer Generic Functions</title>
X!Idrivers/video/fbgen.c
</sect1>
KAO -->
<sect1><title>Frame Buffer Video Mode Database</title>
!Idrivers/video/modedb.c
!Edrivers/video/modedb.c
</sect1>
<sect1><title>Frame Buffer Macintosh Video Mode Database</title>
!Idrivers/video/macmodes.c
</sect1>
<sect1><title>Frame Buffer Fonts</title>
<para>
Refer to the file drivers/video/console/fonts.c for more information.
</para>
<!-- FIXME: Removed for now since no structured comments in source
X!Idrivers/video/console/fonts.c
-->
</sect1>
</chapter>
</book>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="libataDevGuide">
<bookinfo>
<title>libATA Developer's Guide</title>
<authorgroup>
<author>
<firstname>Jeff</firstname>
<surname>Garzik</surname>
</author>
</authorgroup>
<copyright>
<year>2003</year>
<holder>Jeff Garzik</holder>
</copyright>
<legalnotice>
<para>
The contents of this file are subject to the Open
Software License version 1.1 that can be found at
<ulink url="http://www.opensource.org/licenses/osl-1.1.txt">http://www.opensource.org/licenses/osl-1.1.txt</ulink> and is included herein
by reference.
</para>
<para>
Alternatively, the contents of this file may be used under the terms
of the GNU General Public License version 2 (the "GPL") as distributed
in the kernel source COPYING file, in which case the provisions of
the GPL are applicable instead of the above. If you wish to allow
the use of your version of this file only under the terms of the
GPL and not to allow others to use your version of this file under
the OSL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your
version of this file under either the OSL or the GPL.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="libataThanks">
<title>Thanks</title>
<para>
The bulk of the ATA knowledge comes thanks to long conversations with
Andre Hedrick (www.linux-ide.org).
</para>
<para>
Thanks to Alan Cox for pointing out similarities
between SATA and SCSI, and in general for motivation to hack on
libata.
</para>
<para>
libata's device detection
method, ata_pio_devchk, and in general all the early probing was
based on extensive study of Hale Landis's probe/reset code in his
ATADRVR driver (www.ata-atapi.com).
</para>
</chapter>
<chapter id="libataDriverApi">
<title>libata Driver API</title>
<sect1>
<title>struct ata_port_operations</title>
<programlisting>
void (*port_disable) (struct ata_port *);
</programlisting>
<para>
Called from ata_bus_probe() and ata_bus_reset() error paths,
as well as when unregistering from the SCSI module (rmmod, hot
unplug).
</para>
<programlisting>
void (*dev_config) (struct ata_port *, struct ata_device *);
</programlisting>
<para>
Called after IDENTIFY [PACKET] DEVICE is issued to each device
found. Typically used to apply device-specific fixups prior to
issue of SET FEATURES - XFER MODE, and prior to operation.
</para>
<programlisting>
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
void (*post_set_mode) (struct ata_port *ap);
</programlisting>
<para>
Hooks called prior to the issue of SET FEATURES - XFER MODE
command. dev->pio_mode is guaranteed to be valid when
->set_piomode() is called, and dev->dma_mode is guaranteed to be
valid when ->set_dmamode() is called. ->post_set_mode() is
called unconditionally, after the SET FEATURES - XFER MODE
command completes successfully.
</para>
<para>
->set_piomode() is always called (if present), but
->set_dma_mode() is only called if DMA is possible.
</para>
<programlisting>
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
</programlisting>
<para>
->tf_load() is called to load the given taskfile into hardware
registers / DMA buffers. ->tf_read() is called to read the
hardware registers / DMA buffers, to obtain the current set of
taskfile register values.
</para>
<programlisting>
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
</programlisting>
<para>
causes an ATA command, previously loaded with
->tf_load(), to be initiated in hardware.
</para>
<programlisting>
u8 (*check_status)(struct ata_port *ap);
void (*dev_select)(struct ata_port *ap, unsigned int device);
</programlisting>
<para>
Reads the Status ATA shadow register from hardware. On some
hardware, this has the side effect of clearing the interrupt
condition.
</para>
<programlisting>
void (*dev_select)(struct ata_port *ap, unsigned int device);
</programlisting>
<para>
Issues the low-level hardware command(s) that causes one of N
hardware devices to be considered 'selected' (active and
available for use) on the ATA bus.
</para>
<programlisting>
void (*phy_reset) (struct ata_port *ap);
</programlisting>
<para>
The very first step in the probe phase. Actions vary depending
on the bus type, typically. After waking up the device and probing
for device presence (PATA and SATA), typically a soft reset
(SRST) will be performed. Drivers typically use the helper
functions ata_bus_reset() or sata_phy_reset() for this hook.
</para>
<programlisting>
void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc);
</programlisting>
<para>
When setting up an IDE BMDMA transaction, these hooks arm
(->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
engine.
</para>
<programlisting>
void (*qc_prep) (struct ata_queued_cmd *qc);
int (*qc_issue) (struct ata_queued_cmd *qc);
</programlisting>
<para>
Higher-level hooks, these two hooks can potentially supercede
several of the above taskfile/DMA engine hooks. ->qc_prep is
called after the buffers have been DMA-mapped, and is typically
used to populate the hardware's DMA scatter-gather table.
Most drivers use the standard ata_qc_prep() helper function, but
more advanced drivers roll their own.
</para>
<para>
->qc_issue is used to make a command active, once the hardware
and S/G tables have been prepared. IDE BMDMA drivers use the
helper function ata_qc_issue_prot() for taskfile protocol-based
dispatch. More advanced drivers roll their own ->qc_issue
implementation, using this as the "issue new ATA command to
hardware" hook.
</para>
<programlisting>
void (*eng_timeout) (struct ata_port *ap);
</programlisting>
<para>
This is a high level error handling function, called from the
error handling thread, when a command times out.
</para>
<programlisting>
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *);
</programlisting>
<para>
->irq_handler is the interrupt handling routine registered with
the system, by libata. ->irq_clear is called during probe just
before the interrupt handler is registered, to be sure hardware
is quiet.
</para>
<programlisting>
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
u32 val);
</programlisting>
<para>
Read and write standard SATA phy registers. Currently only used
if ->phy_reset hook called the sata_phy_reset() helper function.
</para>
<programlisting>
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
void (*host_stop) (struct ata_host_set *host_set);
</programlisting>
<para>
->port_start() is called just after the data structures for each
port are initialized. Typically this is used to alloc per-port
DMA buffers / tables / rings, enable DMA engines, and similar
tasks.
</para>
<para>
->host_stop() is called when the rmmod or hot unplug process
begins. The hook must stop all hardware interrupts, DMA
engines, etc.
</para>
<para>
->port_stop() is called after ->host_stop(). It's sole function
is to release DMA/memory resources, now that they are no longer
actively being used.
</para>
</sect1>
</chapter>
<chapter id="libataExt">
<title>libata Library</title>
!Edrivers/scsi/libata-core.c
</chapter>
<chapter id="libataInt">
<title>libata Core Internals</title>
!Idrivers/scsi/libata-core.c
</chapter>
<chapter id="libataScsiInt">
<title>libata SCSI translation/emulation</title>
!Edrivers/scsi/libata-scsi.c
!Idrivers/scsi/libata-scsi.c
</chapter>
<chapter id="PiixInt">
<title>ata_piix Internals</title>
!Idrivers/scsi/ata_piix.c
</chapter>
<chapter id="SILInt">
<title>sata_sil Internals</title>
!Idrivers/scsi/sata_sil.c
</chapter>
</book>

View File

@@ -0,0 +1,289 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="Reed-Solomon-Library-Guide">
<bookinfo>
<title>Reed-Solomon Library Programming Interface</title>
<authorgroup>
<author>
<firstname>Thomas</firstname>
<surname>Gleixner</surname>
<affiliation>
<address>
<email>tglx@linutronix.de</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2004</year>
<holder>Thomas Gleixner</holder>
</copyright>
<legalnotice>
<para>
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License version 2 as published by the Free Software Foundation.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The generic Reed-Solomon Library provides encoding, decoding
and error correction functions.
</para>
<para>
Reed-Solomon codes are used in communication and storage
applications to ensure data integrity.
</para>
<para>
This documentation is provided for developers who want to utilize
the functions provided by the library.
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
None.
</para>
</chapter>
<chapter id="usage">
<title>Usage</title>
<para>
This chapter provides examples how to use the library.
</para>
<sect1>
<title>Initializing</title>
<para>
The init function init_rs returns a pointer to a
rs decoder structure, which holds the necessary
information for encoding, decoding and error correction
with the given polynomial. It either uses an existing
matching decoder or creates a new one. On creation all
the lookup tables for fast en/decoding are created.
The function may take a while, so make sure not to
call it in critical code paths.
</para>
<programlisting>
/* the Reed Solomon control structure */
static struct rs_control *rs_decoder;
/* Symbolsize is 10 (bits)
* Primitve polynomial is x^10+x^3+1
* first consecutive root is 0
* primitve element to generate roots = 1
* generator polinomial degree (number of roots) = 6
*/
rs_decoder = init_rs (10, 0x409, 0, 1, 6);
</programlisting>
</sect1>
<sect1>
<title>Encoding</title>
<para>
The encoder calculates the Reed-Solomon code over
the given data length and stores the result in
the parity buffer. Note that the parity buffer must
be initialized before calling the encoder.
</para>
<para>
The expanded data can be inverted on the fly by
providing a non zero inversion mask. The expanded data is
XOR'ed with the mask. This is used e.g. for FLASH
ECC, where the all 0xFF is inverted to an all 0x00.
The Reed-Solomon code for all 0x00 is all 0x00. The
code is inverted before storing to FLASH so it is 0xFF
too. This prevent's that reading from an erased FLASH
results in ECC errors.
</para>
<para>
The databytes are expanded to the given symbol size
on the fly. There is no support for encoding continuous
bitstreams with a symbol size != 8 at the moment. If
it is necessary it should be not a big deal to implement
such functionality.
</para>
<programlisting>
/* Parity buffer. Size = number of roots */
uint16_t par[6];
/* Initialize the parity buffer */
memset(par, 0, sizeof(par));
/* Encode 512 byte in data8. Store parity in buffer par */
encode_rs8 (rs_decoder, data8, 512, par, 0);
</programlisting>
</sect1>
<sect1>
<title>Decoding</title>
<para>
The decoder calculates the syndrome over
the given data length and the received parity symbols
and corrects errors in the data.
</para>
<para>
If a syndrome is available from a hardware decoder
then the syndrome calculation is skipped.
</para>
<para>
The correction of the data buffer can be suppressed
by providing a correction pattern buffer and an error
location buffer to the decoder. The decoder stores the
calculated error location and the correction bitmask
in the given buffers. This is useful for hardware
decoders which use a weird bit ordering scheme.
</para>
<para>
The databytes are expanded to the given symbol size
on the fly. There is no support for decoding continuous
bitstreams with a symbolsize != 8 at the moment. If
it is necessary it should be not a big deal to implement
such functionality.
</para>
<sect2>
<title>
Decoding with syndrome calculation, direct data correction
</title>
<programlisting>
/* Parity buffer. Size = number of roots */
uint16_t par[6];
uint8_t data[512];
int numerr;
/* Receive data */
.....
/* Receive parity */
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, data8, par, 512, NULL, 0, NULL, 0, NULL);
</programlisting>
</sect2>
<sect2>
<title>
Decoding with syndrome given by hardware decoder, direct data correction
</title>
<programlisting>
/* Parity buffer. Size = number of roots */
uint16_t par[6], syn[6];
uint8_t data[512];
int numerr;
/* Receive data */
.....
/* Receive parity */
.....
/* Get syndrome from hardware decoder */
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, data8, par, 512, syn, 0, NULL, 0, NULL);
</programlisting>
</sect2>
<sect2>
<title>
Decoding with syndrome given by hardware decoder, no direct data correction.
</title>
<para>
Note: It's not necessary to give data and received parity to the decoder.
</para>
<programlisting>
/* Parity buffer. Size = number of roots */
uint16_t par[6], syn[6], corr[8];
uint8_t data[512];
int numerr, errpos[8];
/* Receive data */
.....
/* Receive parity */
.....
/* Get syndrome from hardware decoder */
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, NULL, NULL, 512, syn, 0, errpos, 0, corr);
for (i = 0; i &lt; numerr; i++) {
do_error_correction_in_your_buffer(errpos[i], corr[i]);
}
</programlisting>
</sect2>
</sect1>
<sect1>
<title>Cleanup</title>
<para>
The function free_rs frees the allocated resources,
if the caller is the last user of the decoder.
</para>
<programlisting>
/* Release resources */
free_rs(rs_decoder);
</programlisting>
</sect1>
</chapter>
<chapter id="structs">
<title>Structures</title>
<para>
This chapter contains the autogenerated documentation of the structures which are
used in the Reed-Solomon Library and are relevant for a developer.
</para>
!Iinclude/linux/rslib.h
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
<para>
This chapter contains the autogenerated documentation of the Reed-Solomon functions
which are exported.
</para>
!Elib/reed_solomon/reed_solomon.c
</chapter>
<chapter id="credits">
<title>Credits</title>
<para>
The library code for encoding and decoding was written by Phil Karn.
</para>
<programlisting>
Copyright 2002, Phil Karn, KA9Q
May be used under the terms of the GNU General Public License (GPL)
</programlisting>
<para>
The wrapper functions and interfaces are written by Thomas Gleixner
</para>
<para>
Many users have provided bugfixes, improvements and helping hands for testing.
Thanks a lot.
</para>
<para>
The following people have contributed to this document:
</para>
<para>
Thomas Gleixner<email>tglx@linutronix.de</email>
</para>
</chapter>
</book>

View File

@@ -0,0 +1,265 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<article class="whitepaper" id="LinuxSecurityModule" lang="en">
<articleinfo>
<title>Linux Security Modules: General Security Hooks for Linux</title>
<authorgroup>
<author>
<firstname>Stephen</firstname>
<surname>Smalley</surname>
<affiliation>
<orgname>NAI Labs</orgname>
<address><email>ssmalley@nai.com</email></address>
</affiliation>
</author>
<author>
<firstname>Timothy</firstname>
<surname>Fraser</surname>
<affiliation>
<orgname>NAI Labs</orgname>
<address><email>tfraser@nai.com</email></address>
</affiliation>
</author>
<author>
<firstname>Chris</firstname>
<surname>Vance</surname>
<affiliation>
<orgname>NAI Labs</orgname>
<address><email>cvance@nai.com</email></address>
</affiliation>
</author>
</authorgroup>
</articleinfo>
<sect1><title>Introduction</title>
<para>
In March 2001, the National Security Agency (NSA) gave a presentation
about Security-Enhanced Linux (SELinux) at the 2.5 Linux Kernel
Summit. SELinux is an implementation of flexible and fine-grained
nondiscretionary access controls in the Linux kernel, originally
implemented as its own particular kernel patch. Several other
security projects (e.g. RSBAC, Medusa) have also developed flexible
access control architectures for the Linux kernel, and various
projects have developed particular access control models for Linux
(e.g. LIDS, DTE, SubDomain). Each project has developed and
maintained its own kernel patch to support its security needs.
</para>
<para>
In response to the NSA presentation, Linus Torvalds made a set of
remarks that described a security framework he would be willing to
consider for inclusion in the mainstream Linux kernel. He described a
general framework that would provide a set of security hooks to
control operations on kernel objects and a set of opaque security
fields in kernel data structures for maintaining security attributes.
This framework could then be used by loadable kernel modules to
implement any desired model of security. Linus also suggested the
possibility of migrating the Linux capabilities code into such a
module.
</para>
<para>
The Linux Security Modules (LSM) project was started by WireX to
develop such a framework. LSM is a joint development effort by
several security projects, including Immunix, SELinux, SGI and Janus,
and several individuals, including Greg Kroah-Hartman and James
Morris, to develop a Linux kernel patch that implements this
framework. The patch is currently tracking the 2.4 series and is
targeted for integration into the 2.5 development series. This
technical report provides an overview of the framework and the example
capabilities security module provided by the LSM kernel patch.
</para>
</sect1>
<sect1 id="framework"><title>LSM Framework</title>
<para>
The LSM kernel patch provides a general kernel framework to support
security modules. In particular, the LSM framework is primarily
focused on supporting access control modules, although future
development is likely to address other security needs such as
auditing. By itself, the framework does not provide any additional
security; it merely provides the infrastructure to support security
modules. The LSM kernel patch also moves most of the capabilities
logic into an optional security module, with the system defaulting
to the traditional superuser logic. This capabilities module
is discussed further in <xref linkend="cap"/>.
</para>
<para>
The LSM kernel patch adds security fields to kernel data structures
and inserts calls to hook functions at critical points in the kernel
code to manage the security fields and to perform access control. It
also adds functions for registering and unregistering security
modules, and adds a general <function>security</function> system call
to support new system calls for security-aware applications.
</para>
<para>
The LSM security fields are simply <type>void*</type> pointers. For
process and program execution security information, security fields
were added to <structname>struct task_struct</structname> and
<structname>struct linux_binprm</structname>. For filesystem security
information, a security field was added to
<structname>struct super_block</structname>. For pipe, file, and socket
security information, security fields were added to
<structname>struct inode</structname> and
<structname>struct file</structname>. For packet and network device security
information, security fields were added to
<structname>struct sk_buff</structname> and
<structname>struct net_device</structname>. For System V IPC security
information, security fields were added to
<structname>struct kern_ipc_perm</structname> and
<structname>struct msg_msg</structname>; additionally, the definitions
for <structname>struct msg_msg</structname>, <structname>struct
msg_queue</structname>, and <structname>struct
shmid_kernel</structname> were moved to header files
(<filename>include/linux/msg.h</filename> and
<filename>include/linux/shm.h</filename> as appropriate) to allow
the security modules to use these definitions.
</para>
<para>
Each LSM hook is a function pointer in a global table,
security_ops. This table is a
<structname>security_operations</structname> structure as defined by
<filename>include/linux/security.h</filename>. Detailed documentation
for each hook is included in this header file. At present, this
structure consists of a collection of substructures that group related
hooks based on the kernel object (e.g. task, inode, file, sk_buff,
etc) as well as some top-level hook function pointers for system
operations. This structure is likely to be flattened in the future
for performance. The placement of the hook calls in the kernel code
is described by the "called:" lines in the per-hook documentation in
the header file. The hook calls can also be easily found in the
kernel code by looking for the string "security_ops->".
</para>
<para>
Linus mentioned per-process security hooks in his original remarks as a
possible alternative to global security hooks. However, if LSM were
to start from the perspective of per-process hooks, then the base
framework would have to deal with how to handle operations that
involve multiple processes (e.g. kill), since each process might have
its own hook for controlling the operation. This would require a
general mechanism for composing hooks in the base framework.
Additionally, LSM would still need global hooks for operations that
have no process context (e.g. network input operations).
Consequently, LSM provides global security hooks, but a security
module is free to implement per-process hooks (where that makes sense)
by storing a security_ops table in each process' security field and
then invoking these per-process hooks from the global hooks.
The problem of composition is thus deferred to the module.
</para>
<para>
The global security_ops table is initialized to a set of hook
functions provided by a dummy security module that provides
traditional superuser logic. A <function>register_security</function>
function (in <filename>security/security.c</filename>) is provided to
allow a security module to set security_ops to refer to its own hook
functions, and an <function>unregister_security</function> function is
provided to revert security_ops to the dummy module hooks. This
mechanism is used to set the primary security module, which is
responsible for making the final decision for each hook.
</para>
<para>
LSM also provides a simple mechanism for stacking additional security
modules with the primary security module. It defines
<function>register_security</function> and
<function>unregister_security</function> hooks in the
<structname>security_operations</structname> structure and provides
<function>mod_reg_security</function> and
<function>mod_unreg_security</function> functions that invoke these
hooks after performing some sanity checking. A security module can
call these functions in order to stack with other modules. However,
the actual details of how this stacking is handled are deferred to the
module, which can implement these hooks in any way it wishes
(including always returning an error if it does not wish to support
stacking). In this manner, LSM again defers the problem of
composition to the module.
</para>
<para>
Although the LSM hooks are organized into substructures based on
kernel object, all of the hooks can be viewed as falling into two
major categories: hooks that are used to manage the security fields
and hooks that are used to perform access control. Examples of the
first category of hooks include the
<function>alloc_security</function> and
<function>free_security</function> hooks defined for each kernel data
structure that has a security field. These hooks are used to allocate
and free security structures for kernel objects. The first category
of hooks also includes hooks that set information in the security
field after allocation, such as the <function>post_lookup</function>
hook in <structname>struct inode_security_ops</structname>. This hook
is used to set security information for inodes after successful lookup
operations. An example of the second category of hooks is the
<function>permission</function> hook in
<structname>struct inode_security_ops</structname>. This hook checks
permission when accessing an inode.
</para>
</sect1>
<sect1 id="cap"><title>LSM Capabilities Module</title>
<para>
The LSM kernel patch moves most of the existing POSIX.1e capabilities
logic into an optional security module stored in the file
<filename>security/capability.c</filename>. This change allows
users who do not want to use capabilities to omit this code entirely
from their kernel, instead using the dummy module for traditional
superuser logic or any other module that they desire. This change
also allows the developers of the capabilities logic to maintain and
enhance their code more freely, without needing to integrate patches
back into the base kernel.
</para>
<para>
In addition to moving the capabilities logic, the LSM kernel patch
could move the capability-related fields from the kernel data
structures into the new security fields managed by the security
modules. However, at present, the LSM kernel patch leaves the
capability fields in the kernel data structures. In his original
remarks, Linus suggested that this might be preferable so that other
security modules can be easily stacked with the capabilities module
without needing to chain multiple security structures on the security field.
It also avoids imposing extra overhead on the capabilities module
to manage the security fields. However, the LSM framework could
certainly support such a move if it is determined to be desirable,
with only a few additional changes described below.
</para>
<para>
At present, the capabilities logic for computing process capabilities
on <function>execve</function> and <function>set*uid</function>,
checking capabilities for a particular process, saving and checking
capabilities for netlink messages, and handling the
<function>capget</function> and <function>capset</function> system
calls have been moved into the capabilities module. There are still a
few locations in the base kernel where capability-related fields are
directly examined or modified, but the current version of the LSM
patch does allow a security module to completely replace the
assignment and testing of capabilities. These few locations would
need to be changed if the capability-related fields were moved into
the security field. The following is a list of known locations that
still perform such direct examination or modification of
capability-related fields:
<itemizedlist>
<listitem><para><filename>fs/open.c</filename>:<function>sys_access</function></para></listitem>
<listitem><para><filename>fs/lockd/host.c</filename>:<function>nlm_bind_host</function></para></listitem>
<listitem><para><filename>fs/nfsd/auth.c</filename>:<function>nfsd_setuser</function></para></listitem>
<listitem><para><filename>fs/proc/array.c</filename>:<function>task_cap</function></para></listitem>
</itemizedlist>
</para>
</sect1>
</article>

View File

@@ -0,0 +1,3 @@
# Rules are put in Documentation/DocBook
clean-files := *.9.gz *.sgml manpage.links manpage.refs

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="MCAGuide">
<bookinfo>
<title>MCA Driver Programming Interface</title>
<authorgroup>
<author>
<firstname>Alan</firstname>
<surname>Cox</surname>
<affiliation>
<address>
<email>alan@redhat.com</email>
</address>
</affiliation>
</author>
<author>
<firstname>David</firstname>
<surname>Weinehall</surname>
</author>
<author>
<firstname>Chris</firstname>
<surname>Beauregard</surname>
</author>
</authorgroup>
<copyright>
<year>2000</year>
<holder>Alan Cox</holder>
<holder>David Weinehall</holder>
<holder>Chris Beauregard</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The MCA bus functions provide a generalised interface to find MCA
bus cards, to claim them for a driver, and to read and manipulate POS
registers without being aware of the motherboard internals or
certain deep magic specific to onboard devices.
</para>
<para>
The basic interface to the MCA bus devices is the slot. Each slot
is numbered and virtual slot numbers are assigned to the internal
devices. Using a pci_dev as other busses do does not really make
sense in the MCA context as the MCA bus resources require card
specific interpretation.
</para>
<para>
Finally the MCA bus functions provide a parallel set of DMA
functions mimicing the ISA bus DMA functions as closely as possible,
although also supporting the additional DMA functionality on the
MCA bus controllers.
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
None.
</para>
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Earch/i386/kernel/mca.c
</chapter>
<chapter id="dmafunctions">
<title>DMA Functions Provided</title>
!Iinclude/asm-i386/mca_dma.h
</chapter>
</book>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,591 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY procfsexample SYSTEM "procfs_example.xml">
]>
<book id="LKProcfsGuide">
<bookinfo>
<title>Linux Kernel Procfs Guide</title>
<authorgroup>
<author>
<firstname>Erik</firstname>
<othername>(J.A.K.)</othername>
<surname>Mouw</surname>
<affiliation>
<orgname>Delft University of Technology</orgname>
<orgdiv>Faculty of Information Technology and Systems</orgdiv>
<address>
<email>J.A.K.Mouw@its.tudelft.nl</email>
<pob>PO BOX 5031</pob>
<postcode>2600 GA</postcode>
<city>Delft</city>
<country>The Netherlands</country>
</address>
</affiliation>
</author>
</authorgroup>
<revhistory>
<revision>
<revnumber>1.0&nbsp;</revnumber>
<date>May 30, 2001</date>
<revremark>Initial revision posted to linux-kernel</revremark>
</revision>
<revision>
<revnumber>1.1&nbsp;</revnumber>
<date>June 3, 2001</date>
<revremark>Revised after comments from linux-kernel</revremark>
</revision>
</revhistory>
<copyright>
<year>2001</year>
<holder>Erik Mouw</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
This documentation 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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc>
</toc>
<preface>
<title>Preface</title>
<para>
This guide describes the use of the procfs file system from
within the Linux kernel. The idea to write this guide came up on
the #kernelnewbies IRC channel (see <ulink
url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>),
when Jeff Garzik explained the use of procfs and forwarded me a
message Alexander Viro wrote to the linux-kernel mailing list. I
agreed to write it up nicely, so here it is.
</para>
<para>
I'd like to thank Jeff Garzik
<email>jgarzik@pobox.com</email> and Alexander Viro
<email>viro@parcelfarce.linux.theplanet.co.uk</email> for their input,
Tim Waugh <email>twaugh@redhat.com</email> for his <ulink
url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
proofreading.
</para>
<para>
This documentation was written while working on the LART
computing board (<ulink
url="http://www.lart.tudelft.nl/">http://www.lart.tudelft.nl/</ulink>),
which is sponsored by the Mobile Multi-media Communications
(<ulink
url="http://www.mmc.tudelft.nl/">http://www.mmc.tudelft.nl/</ulink>)
and Ubiquitous Communications (<ulink
url="http://www.ubicom.tudelft.nl/">http://www.ubicom.tudelft.nl/</ulink>)
projects.
</para>
<para>
Erik
</para>
</preface>
<chapter id="intro">
<title>Introduction</title>
<para>
The <filename class="directory">/proc</filename> file system
(procfs) is a special file system in the linux kernel. It's a
virtual file system: it is not associated with a block device
but exists only in memory. The files in the procfs are there to
allow userland programs access to certain information from the
kernel (like process information in <filename
class="directory">/proc/[0-9]+/</filename>), but also for debug
purposes (like <filename>/proc/ksyms</filename>).
</para>
<para>
This guide describes the use of the procfs file system from
within the Linux kernel. It starts by introducing all relevant
functions to manage the files within the file system. After that
it shows how to communicate with userland, and some tips and
tricks will be pointed out. Finally a complete example will be
shown.
</para>
<para>
Note that the files in <filename
class="directory">/proc/sys</filename> are sysctl files: they
don't belong to procfs and are governed by a completely
different API described in the Kernel API book.
</para>
</chapter>
<chapter id="managing">
<title>Managing procfs entries</title>
<para>
This chapter describes the functions that various kernel
components use to populate the procfs with files, symlinks,
device nodes, and directories.
</para>
<para>
A minor note before we start: if you want to use any of the
procfs functions, be sure to include the correct header file!
This should be one of the first lines in your code:
</para>
<programlisting>
#include &lt;linux/proc_fs.h&gt;
</programlisting>
<sect1 id="regularfile">
<title>Creating a regular file</title>
<funcsynopsis>
<funcprototype>
<funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef>
<paramdef>const char* <parameter>name</parameter></paramdef>
<paramdef>mode_t <parameter>mode</parameter></paramdef>
<paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
This function creates a regular file with the name
<parameter>name</parameter>, file mode
<parameter>mode</parameter> in the directory
<parameter>parent</parameter>. To create a file in the root of
the procfs, use <constant>NULL</constant> as
<parameter>parent</parameter> parameter. When successful, the
function will return a pointer to the freshly created
<structname>struct proc_dir_entry</structname>; otherwise it
will return <constant>NULL</constant>. <xref
linkend="userland"/> describes how to do something useful with
regular files.
</para>
<para>
Note that it is specifically supported that you can pass a
path that spans multiple directories. For example
<function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>)
will create the <filename class="directory">via0</filename>
directory if necessary, with standard
<constant>0755</constant> permissions.
</para>
<para>
If you only want to be able to read the file, the function
<function>create_proc_read_entry</function> described in <xref
linkend="convenience"/> may be used to create and initialise
the procfs entry in one single call.
</para>
</sect1>
<sect1>
<title>Creating a symlink</title>
<funcsynopsis>
<funcprototype>
<funcdef>struct proc_dir_entry*
<function>proc_symlink</function></funcdef> <paramdef>const
char* <parameter>name</parameter></paramdef>
<paramdef>struct proc_dir_entry*
<parameter>parent</parameter></paramdef> <paramdef>const
char* <parameter>dest</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
This creates a symlink in the procfs directory
<parameter>parent</parameter> that points from
<parameter>name</parameter> to
<parameter>dest</parameter>. This translates in userland to
<literal>ln -s</literal> <parameter>dest</parameter>
<parameter>name</parameter>.
</para>
</sect1>
<sect1>
<title>Creating a directory</title>
<funcsynopsis>
<funcprototype>
<funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef>
<paramdef>const char* <parameter>name</parameter></paramdef>
<paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
Create a directory <parameter>name</parameter> in the procfs
directory <parameter>parent</parameter>.
</para>
</sect1>
<sect1>
<title>Removing an entry</title>
<funcsynopsis>
<funcprototype>
<funcdef>void <function>remove_proc_entry</function></funcdef>
<paramdef>const char* <parameter>name</parameter></paramdef>
<paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
Removes the entry <parameter>name</parameter> in the directory
<parameter>parent</parameter> from the procfs. Entries are
removed by their <emphasis>name</emphasis>, not by the
<structname>struct proc_dir_entry</structname> returned by the
various create functions. Note that this function doesn't
recursively remove entries.
</para>
<para>
Be sure to free the <structfield>data</structfield> entry from
the <structname>struct proc_dir_entry</structname> before
<function>remove_proc_entry</function> is called (that is: if
there was some <structfield>data</structfield> allocated, of
course). See <xref linkend="usingdata"/> for more information
on using the <structfield>data</structfield> entry.
</para>
</sect1>
</chapter>
<chapter id="userland">
<title>Communicating with userland</title>
<para>
Instead of reading (or writing) information directly from
kernel memory, procfs works with <emphasis>call back
functions</emphasis> for files: functions that are called when
a specific file is being read or written. Such functions have
to be initialised after the procfs file is created by setting
the <structfield>read_proc</structfield> and/or
<structfield>write_proc</structfield> fields in the
<structname>struct proc_dir_entry*</structname> that the
function <function>create_proc_entry</function> returned:
</para>
<programlisting>
struct proc_dir_entry* entry;
entry->read_proc = read_proc_foo;
entry->write_proc = write_proc_foo;
</programlisting>
<para>
If you only want to use a the
<structfield>read_proc</structfield>, the function
<function>create_proc_read_entry</function> described in <xref
linkend="convenience"/> may be used to create and initialise the
procfs entry in one single call.
</para>
<sect1>
<title>Reading data</title>
<para>
The read function is a call back function that allows userland
processes to read data from the kernel. The read function
should have the following format:
</para>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>read_func</function></funcdef>
<paramdef>char* <parameter>page</parameter></paramdef>
<paramdef>char** <parameter>start</parameter></paramdef>
<paramdef>off_t <parameter>off</parameter></paramdef>
<paramdef>int <parameter>count</parameter></paramdef>
<paramdef>int* <parameter>eof</parameter></paramdef>
<paramdef>void* <parameter>data</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
The read function should write its information into the
<parameter>page</parameter>. For proper use, the function
should start writing at an offset of
<parameter>off</parameter> in <parameter>page</parameter> and
write at most <parameter>count</parameter> bytes, but because
most read functions are quite simple and only return a small
amount of information, these two parameters are usually
ignored (it breaks pagers like <literal>more</literal> and
<literal>less</literal>, but <literal>cat</literal> still
works).
</para>
<para>
If the <parameter>off</parameter> and
<parameter>count</parameter> parameters are properly used,
<parameter>eof</parameter> should be used to signal that the
end of the file has been reached by writing
<literal>1</literal> to the memory location
<parameter>eof</parameter> points to.
</para>
<para>
The parameter <parameter>start</parameter> doesn't seem to be
used anywhere in the kernel. The <parameter>data</parameter>
parameter can be used to create a single call back function for
several files, see <xref linkend="usingdata"/>.
</para>
<para>
The <function>read_func</function> function must return the
number of bytes written into the <parameter>page</parameter>.
</para>
<para>
<xref linkend="example"/> shows how to use a read call back
function.
</para>
</sect1>
<sect1>
<title>Writing data</title>
<para>
The write call back function allows a userland process to write
data to the kernel, so it has some kind of control over the
kernel. The write function should have the following format:
</para>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>write_func</function></funcdef>
<paramdef>struct file* <parameter>file</parameter></paramdef>
<paramdef>const char* <parameter>buffer</parameter></paramdef>
<paramdef>unsigned long <parameter>count</parameter></paramdef>
<paramdef>void* <parameter>data</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
The write function should read <parameter>count</parameter>
bytes at maximum from the <parameter>buffer</parameter>. Note
that the <parameter>buffer</parameter> doesn't live in the
kernel's memory space, so it should first be copied to kernel
space with <function>copy_from_user</function>. The
<parameter>file</parameter> parameter is usually
ignored. <xref linkend="usingdata"/> shows how to use the
<parameter>data</parameter> parameter.
</para>
<para>
Again, <xref linkend="example"/> shows how to use this call back
function.
</para>
</sect1>
<sect1 id="usingdata">
<title>A single call back for many files</title>
<para>
When a large number of almost identical files is used, it's
quite inconvenient to use a separate call back function for
each file. A better approach is to have a single call back
function that distinguishes between the files by using the
<structfield>data</structfield> field in <structname>struct
proc_dir_entry</structname>. First of all, the
<structfield>data</structfield> field has to be initialised:
</para>
<programlisting>
struct proc_dir_entry* entry;
struct my_file_data *file_data;
file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
entry->data = file_data;
</programlisting>
<para>
The <structfield>data</structfield> field is a <type>void
*</type>, so it can be initialised with anything.
</para>
<para>
Now that the <structfield>data</structfield> field is set, the
<function>read_proc</function> and
<function>write_proc</function> can use it to distinguish
between files because they get it passed into their
<parameter>data</parameter> parameter:
</para>
<programlisting>
int foo_read_func(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
if(data == file_data) {
/* special case for this file */
} else {
/* normal processing */
}
return len;
}
</programlisting>
<para>
Be sure to free the <structfield>data</structfield> data field
when removing the procfs entry.
</para>
</sect1>
</chapter>
<chapter id="tips">
<title>Tips and tricks</title>
<sect1 id="convenience">
<title>Convenience functions</title>
<funcsynopsis>
<funcprototype>
<funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef>
<paramdef>const char* <parameter>name</parameter></paramdef>
<paramdef>mode_t <parameter>mode</parameter></paramdef>
<paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
<paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef>
<paramdef>void* <parameter>data</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
This function creates a regular file in exactly the same way
as <function>create_proc_entry</function> from <xref
linkend="regularfile"/> does, but also allows to set the read
function <parameter>read_proc</parameter> in one call. This
function can set the <parameter>data</parameter> as well, like
explained in <xref linkend="usingdata"/>.
</para>
</sect1>
<sect1>
<title>Modules</title>
<para>
If procfs is being used from within a module, be sure to set
the <structfield>owner</structfield> field in the
<structname>struct proc_dir_entry</structname> to
<constant>THIS_MODULE</constant>.
</para>
<programlisting>
struct proc_dir_entry* entry;
entry->owner = THIS_MODULE;
</programlisting>
</sect1>
<sect1>
<title>Mode and ownership</title>
<para>
Sometimes it is useful to change the mode and/or ownership of
a procfs entry. Here is an example that shows how to achieve
that:
</para>
<programlisting>
struct proc_dir_entry* entry;
entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
entry->uid = 0;
entry->gid = 100;
</programlisting>
</sect1>
</chapter>
<chapter id="example">
<title>Example</title>
<!-- be careful with the example code: it shouldn't be wider than
approx. 60 columns, or otherwise it won't fit properly on a page
-->
&procfsexample;
</chapter>
</book>

View File

@@ -0,0 +1,224 @@
/*
* procfs_example.c: an example proc interface
*
* Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
*
* This file accompanies the procfs-guide in the Linux kernel
* source. Its main use is to demonstrate the concepts and
* functions described in the guide.
*
* This software has been developed while working on the LART
* computing board (http://www.lart.tudelft.nl/), which is
* sponsored by the Mobile Multi-media Communications
* (http://www.mmc.tudelft.nl/) and Ubiquitous Communications
* (http://www.ubicom.tudelft.nl/) projects.
*
* The author can be reached at:
*
* Erik Mouw
* Information and Communication Theory Group
* Faculty of Information Technology and Systems
* Delft University of Technology
* P.O. Box 5031
* 2600 GA Delft
* The Netherlands
*
*
* 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., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>
#define MODULE_VERS "1.0"
#define MODULE_NAME "procfs_example"
#define FOOBAR_LEN 8
struct fb_data_t {
char name[FOOBAR_LEN + 1];
char value[FOOBAR_LEN + 1];
};
static struct proc_dir_entry *example_dir, *foo_file,
*bar_file, *jiffies_file, *symlink;
struct fb_data_t foo_data, bar_data;
static int proc_read_jiffies(char *page, char **start,
off_t off, int count,
int *eof, void *data)
{
int len;
len = sprintf(page, "jiffies = %ld\n",
jiffies);
return len;
}
static int proc_read_foobar(char *page, char **start,
off_t off, int count,
int *eof, void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *)data;
/* DON'T DO THAT - buffer overruns are bad */
len = sprintf(page, "%s = '%s'\n",
fb_data->name, fb_data->value);
return len;
}
static int proc_write_foobar(struct file *file,
const char *buffer,
unsigned long count,
void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *)data;
if(count > FOOBAR_LEN)
len = FOOBAR_LEN;
else
len = count;
if(copy_from_user(fb_data->value, buffer, len))
return -EFAULT;
fb_data->value[len] = '\0';
return len;
}
static int __init init_procfs_example(void)
{
int rv = 0;
/* create directory */
example_dir = proc_mkdir(MODULE_NAME, NULL);
if(example_dir == NULL) {
rv = -ENOMEM;
goto out;
}
example_dir->owner = THIS_MODULE;
/* create jiffies using convenience function */
jiffies_file = create_proc_read_entry("jiffies",
0444, example_dir,
proc_read_jiffies,
NULL);
if(jiffies_file == NULL) {
rv = -ENOMEM;
goto no_jiffies;
}
jiffies_file->owner = THIS_MODULE;
/* create foo and bar files using same callback
* functions
*/
foo_file = create_proc_entry("foo", 0644, example_dir);
if(foo_file == NULL) {
rv = -ENOMEM;
goto no_foo;
}
strcpy(foo_data.name, "foo");
strcpy(foo_data.value, "foo");
foo_file->data = &foo_data;
foo_file->read_proc = proc_read_foobar;
foo_file->write_proc = proc_write_foobar;
foo_file->owner = THIS_MODULE;
bar_file = create_proc_entry("bar", 0644, example_dir);
if(bar_file == NULL) {
rv = -ENOMEM;
goto no_bar;
}
strcpy(bar_data.name, "bar");
strcpy(bar_data.value, "bar");
bar_file->data = &bar_data;
bar_file->read_proc = proc_read_foobar;
bar_file->write_proc = proc_write_foobar;
bar_file->owner = THIS_MODULE;
/* create symlink */
symlink = proc_symlink("jiffies_too", example_dir,
"jiffies");
if(symlink == NULL) {
rv = -ENOMEM;
goto no_symlink;
}
symlink->owner = THIS_MODULE;
/* everything OK */
printk(KERN_INFO "%s %s initialised\n",
MODULE_NAME, MODULE_VERS);
return 0;
no_symlink:
remove_proc_entry("tty", example_dir);
no_tty:
remove_proc_entry("bar", example_dir);
no_bar:
remove_proc_entry("foo", example_dir);
no_foo:
remove_proc_entry("jiffies", example_dir);
no_jiffies:
remove_proc_entry(MODULE_NAME, NULL);
out:
return rv;
}
static void __exit cleanup_procfs_example(void)
{
remove_proc_entry("jiffies_too", example_dir);
remove_proc_entry("tty", example_dir);
remove_proc_entry("bar", example_dir);
remove_proc_entry("foo", example_dir);
remove_proc_entry("jiffies", example_dir);
remove_proc_entry(MODULE_NAME, NULL);
printk(KERN_INFO "%s %s removed\n",
MODULE_NAME, MODULE_VERS);
}
module_init(init_procfs_example);
module_exit(cleanup_procfs_example);
MODULE_AUTHOR("Erik Mouw");
MODULE_DESCRIPTION("procfs examples");

View File

@@ -0,0 +1,193 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="scsidrivers">
<bookinfo>
<title>SCSI Subsystem Interfaces</title>
<authorgroup>
<author>
<firstname>Douglas</firstname>
<surname>Gilbert</surname>
<affiliation>
<address>
<email>dgilbert@interlog.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<pubdate>2003-08-11</pubdate>
<copyright>
<year>2002</year>
<year>2003</year>
<holder>Douglas Gilbert</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
This document outlines the interface between the Linux scsi mid level
and lower level drivers. Lower level drivers are variously called HBA
(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
The latter alludes to the fact that a lower level driver may be a
bridge to another IO subsystem (and the "ide-scsi" driver is an example
of this). There can be many lower level drivers active in a running
system, but only one per hardware type. For example, the aic7xxx driver
controls adaptec controllers based on the 7xxx chip series. Most lower
level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
</para>
<para>
This document can been found in an ASCII text file in the linux kernel
source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
It currently hold a little more information than this document. The
<filename>drivers/scsi/hosts.h</filename> and <filename>
drivers/scsi/scsi.h</filename> headers contain descriptions of members
of important structures for the scsi subsystem.
</para>
</chapter>
<chapter id="driver-struct">
<title>Driver structure</title>
<para>
Traditionally a lower level driver for the scsi subsystem has been
at least two files in the drivers/scsi directory. For example, a
driver called "xyz" has a header file "xyz.h" and a source file
"xyz.c". [Actually there is no good reason why this couldn't all
be in one file.] Some drivers that have been ported to several operating
systems (e.g. aic7xxx which has separate files for generic and
OS-specific code) have more than two files. Such drivers tend to have
their own directory under the drivers/scsi directory.
</para>
<para>
scsi_module.c is normally included at the end of a lower
level driver. For it to work a declaration like this is needed before
it is included:
<programlisting>
static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
/* DRIVER_TEMPLATE should contain pointers to supported interface
functions. Scsi_Host_Template is defined hosts.h */
#include "scsi_module.c"
</programlisting>
</para>
<para>
The scsi_module.c assumes the name "driver_template" is appropriately
defined. It contains 2 functions:
<orderedlist>
<listitem><para>
init_this_scsi_driver() called during builtin and module driver
initialization: invokes mid level's scsi_register_host()
</para></listitem>
<listitem><para>
exit_this_scsi_driver() called during closedown: invokes
mid level's scsi_unregister_host()
</para></listitem>
</orderedlist>
</para>
<para>
When a new, lower level driver is being added to Linux, the following
files (all found in the drivers/scsi directory) will need some attention:
Makefile, Config.help and Config.in . It is probably best to look at what
an existing lower level driver does in this regard.
</para>
</chapter>
<chapter id="intfunctions">
<title>Interface Functions</title>
!EDocumentation/scsi/scsi_mid_low_api.txt
</chapter>
<chapter id="locks">
<title>Locks</title>
<para>
Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
which is initialized in scsi_register() [found in hosts.c]. Within the
same function the Scsi_Host::host_lock pointer is initialized to point
at default_lock with the scsi_assign_lock() function. Thereafter
lock and unlock operations performed by the mid level use the
Scsi_Host::host_lock pointer.
</para>
<para>
Lower level drivers can override the use of Scsi_Host::default_lock by
using scsi_assign_lock(). The earliest opportunity to do this would
be in the detect() function after it has invoked scsi_register(). It
could be replaced by a coarser grain lock (e.g. per driver) or a
lock of equal granularity (i.e. per host). Using finer grain locks
(e.g. per scsi device) may be possible by juggling locks in
queuecommand().
</para>
</chapter>
<chapter id="changes">
<title>Changes since lk 2.4 series</title>
<para>
io_request_lock has been replaced by several finer grained locks. The lock
relevant to lower level drivers is Scsi_Host::host_lock and there is one
per scsi host.
</para>
<para>
The older error handling mechanism has been removed. This means the
lower level interface functions abort() and reset() have been removed.
</para>
<para>
In the 2.4 series the scsi subsystem configuration descriptions were
aggregated with the configuration descriptions from all other Linux
subsystems in the Documentation/Configure.help file. In the 2.5 series,
the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
file.
</para>
</chapter>
<chapter id="credits">
<title>Credits</title>
<para>
The following people have contributed to this document:
<orderedlist>
<listitem><para>
Mike Anderson <email>andmike@us.ibm.com</email>
</para></listitem>
<listitem><para>
James Bottomley <email>James.Bottomley@steeleye.com</email>
</para></listitem>
<listitem><para>
Patrick Mansfield <email>patmans@us.ibm.com</email>
</para></listitem>
</orderedlist>
</para>
</chapter>
</book>

View File

@@ -0,0 +1,585 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="SiS900Guide">
<bookinfo>
<title>SiS 900/7016 Fast Ethernet Device Driver</title>
<authorgroup>
<author>
<firstname>Ollie</firstname>
<surname>Lho</surname>
</author>
<author>
<firstname>Lei Chun</firstname>
<surname>Chang</surname>
</author>
</authorgroup>
<edition>Document Revision: 0.3 for SiS900 driver v1.06 &amp; v1.07</edition>
<pubdate>November 16, 2000</pubdate>
<copyright>
<year>1999</year>
<holder>Silicon Integrated System Corp.</holder>
</copyright>
<legalnotice>
<para>
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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
</para>
</legalnotice>
<abstract>
<para>
This document gives some information on installation and usage of SiS 900/7016
device driver under Linux.
</para>
</abstract>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
This document describes the revision 1.06 and 1.07 of SiS 900/7016 Fast Ethernet
device driver under Linux. The driver is developed by Silicon Integrated
System Corp. and distributed freely under the GNU General Public License (GPL).
The driver can be compiled as a loadable module and used under Linux kernel
version 2.2.x. (rev. 1.06)
With minimal changes, the driver can also be used under 2.3.x and 2.4.x kernel
(rev. 1.07), please see
<xref linkend="install"/>. If you are intended to
use the driver for earlier kernels, you are on your own.
</para>
<para>
The driver is tested with usual TCP/IP applications including
FTP, Telnet, Netscape etc. and is used constantly by the developers.
</para>
<para>
Please send all comments/fixes/questions to
<ulink url="mailto:lcchang@sis.com.tw">Lei-Chun Chang</ulink>.
</para>
</chapter>
<chapter id="changes">
<title>Changes</title>
<para>
Changes made in Revision 1.07
<orderedlist>
<listitem>
<para>
Separation of sis900.c and sis900.h in order to move most
constant definition to sis900.h (many of those constants were
corrected)
</para>
</listitem>
<listitem>
<para>
Clean up PCI detection, the pci-scan from Donald Becker were not used,
just simple pci&lowbar;find&lowbar;*.
</para>
</listitem>
<listitem>
<para>
MII detection is modified to support multiple mii transceiver.
</para>
</listitem>
<listitem>
<para>
Bugs in read&lowbar;eeprom, mdio&lowbar;* were removed.
</para>
</listitem>
<listitem>
<para>
Lot of sis900 irrelevant comments were removed/changed and
more comments were added to reflect the real situation.
</para>
</listitem>
<listitem>
<para>
Clean up of physical/virtual address space mess in buffer
descriptors.
</para>
</listitem>
<listitem>
<para>
Better transmit/receive error handling.
</para>
</listitem>
<listitem>
<para>
The driver now uses zero-copy single buffer management
scheme to improve performance.
</para>
</listitem>
<listitem>
<para>
Names of variables were changed to be more consistent.
</para>
</listitem>
<listitem>
<para>
Clean up of auo-negotiation and timer code.
</para>
</listitem>
<listitem>
<para>
Automatic detection and change of PHY on the fly.
</para>
</listitem>
<listitem>
<para>
Bug in mac probing fixed.
</para>
</listitem>
<listitem>
<para>
Fix 630E equalier problem by modifying the equalizer workaround rule.
</para>
</listitem>
<listitem>
<para>
Support for ICS1893 10/100 Interated PHYceiver.
</para>
</listitem>
<listitem>
<para>
Support for media select by ifconfig.
</para>
</listitem>
<listitem>
<para>
Added kernel-doc extratable documentation.
</para>
</listitem>
</orderedlist>
</para>
</chapter>
<chapter id="tested">
<title>Tested Environment</title>
<para>
This driver is developed on the following hardware
<itemizedlist>
<listitem>
<para>
Intel Celeron 500 with SiS 630 (rev 02) chipset
</para>
</listitem>
<listitem>
<para>
SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card
</para>
</listitem>
</itemizedlist>
and tested with these software environments
<itemizedlist>
<listitem>
<para>
Red Hat Linux version 6.2
</para>
</listitem>
<listitem>
<para>
Linux kernel version 2.4.0
</para>
</listitem>
<listitem>
<para>
Netscape version 4.6
</para>
</listitem>
<listitem>
<para>
NcFTP 3.0.0 beta 18
</para>
</listitem>
<listitem>
<para>
Samba version 2.0.3
</para>
</listitem>
</itemizedlist>
</para>
</chapter>
<chapter id="files">
<title>Files in This Package</title>
<para>
In the package you can find these files:
</para>
<para>
<variablelist>
<varlistentry>
<term>sis900.c</term>
<listitem>
<para>
Driver source file in C
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>sis900.h</term>
<listitem>
<para>
Header file for sis900.c
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>sis900.sgml</term>
<listitem>
<para>
DocBook SGML source of the document
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>sis900.txt</term>
<listitem>
<para>
Driver document in plain text
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</chapter>
<chapter id="install">
<title>Installation</title>
<para>
Silicon Integrated System Corp. is cooperating closely with core Linux Kernel
developers. The revisions of SiS 900 driver are distributed by the usuall channels
for kernel tar files and patches. Those kernel tar files for official kernel and
patches for kernel pre-release can be download at
<ulink url="http://ftp.kernel.org/pub/linux/kernel/">official kernel ftp site</ulink>
and its mirrors.
The 1.06 revision can be found in kernel version later than 2.3.15 and pre-2.2.14,
and 1.07 revision can be found in kernel version 2.4.0.
If you have no prior experience in networking under Linux, please read
<ulink url="http://www.tldp.org/">Ethernet HOWTO</ulink> and
<ulink url="http://www.tldp.org/">Networking HOWTO</ulink> available from
Linux Documentation Project (LDP).
</para>
<para>
The driver is bundled in release later than 2.2.11 and 2.3.15 so this
is the most easy case.
Be sure you have the appropriate packages for compiling kernel source.
Those packages are listed in Document/Changes in kernel source
distribution. If you have to install the driver other than those bundled
in kernel release, you should have your driver file
<filename>sis900.c</filename> and <filename>sis900.h</filename>
copied into <filename class="directory">/usr/src/linux/drivers/net/</filename> first.
There are two alternative ways to install the driver
</para>
<sect1>
<title>Building the driver as loadable module</title>
<para>
To build the driver as a loadable kernel module you have to reconfigure
the kernel to activate network support by
</para>
<para><screen>
make menuconfig
</screen></para>
<para>
Choose <quote>Loadable module support ---></quote>,
then select <quote>Enable loadable module support</quote>.
</para>
<para>
Choose <quote>Network Device Support ---></quote>, select
<quote>Ethernet (10 or 100Mbit)</quote>.
Then select <quote>EISA, VLB, PCI and on board controllers</quote>,
and choose <quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote>
to <quote>M</quote>.
</para>
<para>
After reconfiguring the kernel, you can make the driver module by
</para>
<para><screen>
make modules
</screen></para>
<para>
The driver should be compiled with no errors. After compiling the driver,
the driver can be installed to proper place by
</para>
<para><screen>
make modules_install
</screen></para>
<para>
Load the driver into kernel by
</para>
<para><screen>
insmod sis900
</screen></para>
<para>
When loading the driver into memory, some information message can be view by
</para>
<para>
<screen>
dmesg
</screen>
or
<screen>
cat /var/log/message
</screen>
</para>
<para>
If the driver is loaded properly you will have messages similar to this:
</para>
<para><screen>
sis900.c: v1.07.06 11/07/2000
eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4.
eth0: SiS 900 Internal MII PHY transceiver found at address 1.
eth0: Using SiS 900 Internal MII PHY as default
</screen></para>
<para>
showing the version of the driver and the results of probing routine.
</para>
<para>
Once the driver is loaded, network can be brought up by
</para>
<para><screen>
/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE
</screen></para>
<para>
where IPADDR, BROADCAST, NETMASK are your IP address, broadcast address and
netmask respectively. TYPE is used to set medium type used by the device.
Typical values are "10baseT"(twisted-pair 10Mbps Ethernet) or "100baseT"
(twisted-pair 100Mbps Ethernet). For more information on how to configure
network interface, please refer to
<ulink url="http://www.tldp.org/">Networking HOWTO</ulink>.
</para>
<para>
The link status is also shown by kernel messages. For example, after the
network interface is activated, you may have the message:
</para>
<para><screen>
eth0: Media Link On 100mbps full-duplex
</screen></para>
<para>
If you try to unplug the twist pair (TP) cable you will get
</para>
<para><screen>
eth0: Media Link Off
</screen></para>
<para>
indicating that the link is failed.
</para>
</sect1>
<sect1>
<title>Building the driver into kernel</title>
<para>
If you want to make the driver into kernel, choose <quote>Y</quote>
rather than <quote>M</quote> on
<quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote>
when configuring the kernel. Build the kernel image in the usual way
</para>
<para><screen>
make clean
make bzlilo
</screen></para>
<para>
Next time the system reboot, you have the driver in memory.
</para>
</sect1>
</chapter>
<chapter id="problems">
<title>Known Problems and Bugs</title>
<para>
There are some known problems and bugs. If you find any other bugs please
mail to <ulink url="mailto:lcchang@sis.com.tw">lcchang@sis.com.tw</ulink>
<orderedlist>
<listitem>
<para>
AM79C901 HomePNA PHY is not thoroughly tested, there may be some
bugs in the <quote>on the fly</quote> change of transceiver.
</para>
</listitem>
<listitem>
<para>
A bug is hidden somewhere in the receive buffer management code,
the bug causes NULL pointer reference in the kernel. This fault is
caught before bad things happen and reported with the message:
<computeroutput>
eth0: NULL pointer encountered in Rx ring, skipping
</computeroutput>
which can be viewed with <literal remap="tt">dmesg</literal> or
<literal remap="tt">cat /var/log/message</literal>.
</para>
</listitem>
<listitem>
<para>
The media type change from 10Mbps to 100Mbps twisted-pair ethernet
by ifconfig causes the media link down.
</para>
</listitem>
</orderedlist>
</para>
</chapter>
<chapter id="RHistory">
<title>Revision History</title>
<para>
<itemizedlist>
<listitem>
<para>
November 13, 2000, Revision 1.07, seventh release, 630E problem fixed
and further clean up.
</para>
</listitem>
<listitem>
<para>
November 4, 1999, Revision 1.06, Second release, lots of clean up
and optimization.
</para>
</listitem>
<listitem>
<para>
August 8, 1999, Revision 1.05, Initial Public Release
</para>
</listitem>
</itemizedlist>
</para>
</chapter>
<chapter id="acknowledgements">
<title>Acknowledgements</title>
<para>
This driver was originally derived form
<ulink url="mailto:becker@cesdis1.gsfc.nasa.gov">Donald Becker</ulink>'s
<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/pci-skeleton.c"
>pci-skeleton</ulink> and
<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/rtl8139.c"
>rtl8139</ulink> drivers. Donald also provided various suggestion
regarded with improvements made in revision 1.06.
</para>
<para>
The 1.05 revision was created by
<ulink url="mailto:cmhuang@sis.com.tw">Jim Huang</ulink>, AMD 79c901
support was added by <ulink url="mailto:lcs@sis.com.tw">Chin-Shan Li</ulink>.
</para>
</chapter>
<chapter id="functions">
<title>List of Functions</title>
!Idrivers/net/sis900.c
</chapter>
</book>

View File

@@ -0,0 +1,327 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="TulipUserGuide">
<bookinfo>
<title>Tulip Driver User's Guide</title>
<authorgroup>
<author>
<firstname>Jeff</firstname>
<surname>Garzik</surname>
<affiliation>
<address>
<email>jgarzik@pobox.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2001</year>
<holder>Jeff Garzik</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The Tulip Ethernet Card Driver
is maintained by Jeff Garzik (<email>jgarzik@pobox.com</email>).
</para>
<para>
The Tulip driver was developed by Donald Becker and changed by
Jeff Garzik, Takashi Manabe and a cast of thousands.
</para>
<para>
For 2.4.x and later kernels, the Linux Tulip driver is available at
<ulink url="http://sourceforge.net/projects/tulip/">http://sourceforge.net/projects/tulip/</ulink>
</para>
<para>
This driver is for the Digital "Tulip" Ethernet adapter interface.
It should work with most DEC 21*4*-based chips/ethercards, as well as
with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
</para>
<para>
The original author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation,
410 Severn Ave., Suite 210,
Annapolis MD 21403
</para>
<para>
Additional information on Donald Becker's tulip.c
is available at <ulink url="http://www.scyld.com/network/tulip.html">http://www.scyld.com/network/tulip.html</ulink>
</para>
</chapter>
<chapter id="drvr-compat">
<title>Driver Compatibility</title>
<para>
This device driver is designed for the DECchip "Tulip", Digital's
single-chip ethernet controllers for PCI (now owned by Intel).
Supported members of the family
are the 21040, 21041, 21140, 21140A, 21142, and 21143. Similar work-alike
chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
supported.
</para>
<para>
These chips are used on at least 140 unique PCI board designs. The great
number of chips and board designs supported is the reason for the
driver size and complexity. Almost of the increasing complexity is in the
board configuration and media selection code. There is very little
increasing in the operational critical path length.
</para>
</chapter>
<chapter id="board-settings">
<title>Board-specific Settings</title>
<para>
PCI bus devices are configured by the system at boot time, so no jumpers
need to be set on the board. The system BIOS preferably should assign the
PCI INTA signal to an otherwise unused system IRQ line.
</para>
<para>
Some boards have EEPROMs tables with default media entry. The factory default
is usually "autoselect". This should only be overridden when using
transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
for forcing full-duplex when used with old link partners that do not do
autonegotiation.
</para>
</chapter>
<chapter id="driver-operation">
<title>Driver Operation</title>
<sect1><title>Ring buffers</title>
<para>
The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
This driver uses statically allocated rings of Rx and Tx descriptors, set at
compile time by RX/TX_RING_SIZE. This version of the driver allocates skbuffs
for the Rx ring buffers at open() time and passes the skb->data field to the
Tulip as receive data buffers. When an incoming frame is less than
RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
copied to the new skbuff. When the incoming frame is larger, the skbuff is
passed directly up the protocol stack and replaced by a newly allocated
skbuff.
</para>
<para>
The RX_COPYBREAK value is chosen to trade-off the memory wasted by
using a full-sized skbuff for small frames vs. the copying costs of larger
frames. For small frames the copying cost is negligible (esp. considering
that we are pre-loading the cache with immediately useful header
information). For large frames the copying cost is non-trivial, and the
larger copy might flush the cache of useful data. A subtle aspect of this
choice is that the Tulip only receives into longword aligned buffers, thus
the IP header at offset 14 isn't longword aligned for further processing.
Copied frames are put into the new skbuff at an offset of "+2", thus copying
has the beneficial effect of aligning the IP header and preloading the
cache.
</para>
</sect1>
<sect1><title>Synchronization</title>
<para>
The driver runs as two independent, single-threaded flows of control. One
is the send-packet routine, which enforces single-threaded use by the
dev->tbusy flag. The other thread is the interrupt handler, which is single
threaded by the hardware and other software.
</para>
<para>
The send packet thread has partial control over the Tx ring and 'dev->tbusy'
flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next
queue slot is empty, it clears the tbusy flag when finished otherwise it sets
the 'tp->tx_full' flag.
</para>
<para>
The interrupt handler has exclusive control over the Rx ring and records stats
from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so
we can't avoid the interrupt overhead by having the Tx routine reap the Tx
stats.) After reaping the stats, it marks the queue entry as empty by setting
the 'base' to zero. Iff the 'tp->tx_full' flag is set, it clears both the
tx_full and tbusy flags.
</para>
</sect1>
</chapter>
<chapter id="errata">
<title>Errata</title>
<para>
The old DEC databooks were light on details.
The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
register of the set CSR12-15 written. Hmmm, now how is that possible?
</para>
<para>
The DEC SROM format is very badly designed not precisely defined, leading to
part of the media selection junkheap below. Some boards do not have EEPROM
media tables and need to be patched up. Worse, other boards use the DEC
design kit media table when it isn't correct for their board.
</para>
<para>
We cannot use MII interrupts because there is no defined GPIO pin to attach
them. The MII transceiver status is polled using an kernel timer.
</para>
</chapter>
<chapter id="changelog">
<title>Driver Change History</title>
<sect1><title>Version 0.9.14 (February 20, 2001)</title>
<itemizedlist>
<listitem><para>Fix PNIC problems (Manfred Spraul)</para></listitem>
<listitem><para>Add new PCI id for Accton comet</para></listitem>
<listitem><para>Support Davicom tulips</para></listitem>
<listitem><para>Fix oops in eeprom parsing</para></listitem>
<listitem><para>Enable workarounds for early PCI chipsets</para></listitem>
<listitem><para>IA64, hppa csr0 support</para></listitem>
<listitem><para>Support media types 5, 6</para></listitem>
<listitem><para>Interpret a bit more of the 21142 SROM extended media type 3</para></listitem>
<listitem><para>Add missing delay in eeprom reading</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.11 (November 3, 2000)</title>
<itemizedlist>
<listitem><para>Eliminate extra bus accesses when sharing interrupts (prumpf)</para></listitem>
<listitem><para>Barrier following ownership descriptor bit flip (prumpf)</para></listitem>
<listitem><para>Endianness fixes for >14 addresses in setup frames (prumpf)</para></listitem>
<listitem><para>Report link beat to kernel/userspace via netif_carrier_*. (kuznet)</para></listitem>
<listitem><para>Better spinlocking in set_rx_mode.</para></listitem>
<listitem><para>Fix I/O resource request failure error messages (DaveM catch)</para></listitem>
<listitem><para>Handle DMA allocation failure.</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.10 (September 6, 2000)</title>
<itemizedlist>
<listitem><para>Simple interrupt mitigation (via jamal)</para></listitem>
<listitem><para>More PCI ids</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.9 (August 11, 2000)</title>
<itemizedlist>
<listitem><para>More PCI ids</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.8 (July 13, 2000)</title>
<itemizedlist>
<listitem><para>Correct signed/unsigned comparison for dummy frame index</para></listitem>
<listitem><para>Remove outdated references to struct enet_statistics</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.7 (June 17, 2000)</title>
<itemizedlist>
<listitem><para>Timer cleanups (Andrew Morton)</para></listitem>
<listitem><para>Alpha compile fix (somebody?)</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.6 (May 31, 2000)</title>
<itemizedlist>
<listitem><para>Revert 21143-related support flag patch</para></listitem>
<listitem><para>Add HPPA/media-table debugging printk</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.5 (May 30, 2000)</title>
<itemizedlist>
<listitem><para>HPPA support (willy@puffingroup)</para></listitem>
<listitem><para>CSR6 bits and tulip.h cleanup (Chris Smith)</para></listitem>
<listitem><para>Improve debugging messages a bit</para></listitem>
<listitem><para>Add delay after CSR13 write in t21142_start_nway</para></listitem>
<listitem><para>Remove unused ETHER_STATS code</para></listitem>
<listitem><para>Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith)</para></listitem>
<listitem><para>Update DS21143 support flags in tulip_chip_info[]</para></listitem>
<listitem><para>Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit()</para></listitem>
<listitem><para>Add locking to set_rx_mode()</para></listitem>
<listitem><para>Fix race with chip setting DescOwned bit (Hal Murray)</para></listitem>
<listitem><para>Request 100% of PIO and MMIO resource space assigned to card</para></listitem>
<listitem><para>Remove error message from pci_enable_device failure</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.4.3 (April 14, 2000)</title>
<itemizedlist>
<listitem><para>mod_timer fix (Hal Murray)</para></listitem>
<listitem><para>PNIC2 resuscitation (Chris Smith)</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.4.2 (March 21, 2000)</title>
<itemizedlist>
<listitem><para>Fix 21041 CSR7, CSR13/14/15 handling</para></listitem>
<listitem><para>Merge some PCI ids from tulip 0.91x</para></listitem>
<listitem><para>Merge some HAS_xxx flags and flag settings from tulip 0.91x</para></listitem>
<listitem><para>asm/io.h fix (submitted by many) and cleanup</para></listitem>
<listitem><para>s/HAS_NWAY143/HAS_NWAY/</para></listitem>
<listitem><para>Cleanup 21041 mode reporting</para></listitem>
<listitem><para>Small code cleanups</para></listitem>
</itemizedlist>
</sect1>
<sect1><title>Version 0.9.4.1 (March 18, 2000)</title>
<itemizedlist>
<listitem><para>Finish PCI DMA conversion (davem)</para></listitem>
<listitem><para>Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet)</para></listitem>
<listitem><para>PCI DMA fix (kuznet)</para></listitem>
<listitem><para>eeprom.c code cleanup</para></listitem>
<listitem><para>Remove Xircom Tulip crud</para></listitem>
</itemizedlist>
</sect1>
</chapter>
</book>

View File

@@ -0,0 +1,979 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="Linux-USB-API">
<bookinfo>
<title>The Linux-USB Host Side API</title>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction to USB on Linux</title>
<para>A Universal Serial Bus (USB) is used to connect a host,
such as a PC or workstation, to a number of peripheral
devices. USB uses a tree structure, with the host at the
root (the system's master), hubs as interior nodes, and
peripheral devices as leaves (and slaves).
Modern PCs support several such trees of USB devices, usually
one USB 2.0 tree (480 Mbit/sec each) with
a few USB 1.1 trees (12 Mbit/sec each) that are used when you
connect a USB 1.1 device directly to the machine's "root hub".
</para>
<para>That master/slave asymmetry was designed in part for
ease of use. It is not physically possible to assemble
(legal) USB cables incorrectly: all upstream "to-the-host"
connectors are the rectangular type, matching the sockets on
root hubs, and the downstream type are the squarish type
(or they are built in to the peripheral).
Software doesn't need to deal with distributed autoconfiguration
since the pre-designated master node manages all that.
At the electrical level, bus protocol overhead is reduced by
eliminating arbitration and moving scheduling into host software.
</para>
<para>USB 1.0 was announced in January 1996, and was revised
as USB 1.1 (with improvements in hub specification and
support for interrupt-out transfers) in September 1998.
USB 2.0 was released in April 2000, including high speed
transfers and transaction translating hubs (used for USB 1.1
and 1.0 backward compatibility).
</para>
<para>USB support was added to Linux early in the 2.2 kernel series
shortly before the 2.3 development forked off. Updates
from 2.3 were regularly folded back into 2.2 releases, bringing
new features such as <filename>/sbin/hotplug</filename> support,
more drivers, and more robustness.
The 2.5 kernel series continued such improvements, and also
worked on USB 2.0 support,
higher performance,
better consistency between host controller drivers,
API simplification (to make bugs less likely),
and providing internal "kerneldoc" documentation.
</para>
<para>Linux can run inside USB devices as well as on
the hosts that control the devices.
Because the Linux 2.x USB support evolved to support mass market
platforms such as Apple Macintosh or PC-compatible systems,
it didn't address design concerns for those types of USB systems.
So it can't be used inside mass-market PDAs, or other peripherals.
USB device drivers running inside those Linux peripherals
don't do the same things as the ones running inside hosts,
and so they've been given a different name:
they're called <emphasis>gadget drivers</emphasis>.
This document does not present gadget drivers.
</para>
</chapter>
<chapter id="host">
<title>USB Host-Side API Model</title>
<para>Within the kernel,
host-side drivers for USB devices talk to the "usbcore" APIs.
There are two types of public "usbcore" APIs, targetted at two different
layers of USB driver. Those are
<emphasis>general purpose</emphasis> drivers, exposed through
driver frameworks such as block, character, or network devices;
and drivers that are <emphasis>part of the core</emphasis>,
which are involved in managing a USB bus.
Such core drivers include the <emphasis>hub</emphasis> driver,
which manages trees of USB devices, and several different kinds
of <emphasis>host controller driver (HCD)</emphasis>,
which control individual busses.
</para>
<para>The device model seen by USB drivers is relatively complex.
</para>
<itemizedlist>
<listitem><para>USB supports four kinds of data transfer
(control, bulk, interrupt, and isochronous). Two transfer
types use bandwidth as it's available (control and bulk),
while the other two types of transfer (interrupt and isochronous)
are scheduled to provide guaranteed bandwidth.
</para></listitem>
<listitem><para>The device description model includes one or more
"configurations" per device, only one of which is active at a time.
Devices that are capable of high speed operation must also support
full speed configurations, along with a way to ask about the
"other speed" configurations that might be used.
</para></listitem>
<listitem><para>Configurations have one or more "interface", each
of which may have "alternate settings". Interfaces may be
standardized by USB "Class" specifications, or may be specific to
a vendor or device.</para>
<para>USB device drivers actually bind to interfaces, not devices.
Think of them as "interface drivers", though you
may not see many devices where the distinction is important.
<emphasis>Most USB devices are simple, with only one configuration,
one interface, and one alternate setting.</emphasis>
</para></listitem>
<listitem><para>Interfaces have one or more "endpoints", each of
which supports one type and direction of data transfer such as
"bulk out" or "interrupt in". The entire configuration may have
up to sixteen endpoints in each direction, allocated as needed
among all the interfaces.
</para></listitem>
<listitem><para>Data transfer on USB is packetized; each endpoint
has a maximum packet size.
Drivers must often be aware of conventions such as flagging the end
of bulk transfers using "short" (including zero length) packets.
</para></listitem>
<listitem><para>The Linux USB API supports synchronous calls for
control and bulk messaging.
It also supports asynchnous calls for all kinds of data transfer,
using request structures called "URBs" (USB Request Blocks).
</para></listitem>
</itemizedlist>
<para>Accordingly, the USB Core API exposed to device drivers
covers quite a lot of territory. You'll probably need to consult
the USB 2.0 specification, available online from www.usb.org at
no cost, as well as class or device specifications.
</para>
<para>The only host-side drivers that actually touch hardware
(reading/writing registers, handling IRQs, and so on) are the HCDs.
In theory, all HCDs provide the same functionality through the same
API. In practice, that's becoming more true on the 2.5 kernels,
but there are still differences that crop up especially with
fault handling. Different controllers don't necessarily report
the same aspects of failures, and recovery from faults (including
software-induced ones like unlinking an URB) isn't yet fully
consistent.
Device driver authors should make a point of doing disconnect
testing (while the device is active) with each different host
controller driver, to make sure drivers don't have bugs of
their own as well as to make sure they aren't relying on some
HCD-specific behavior.
(You will need external USB 1.1 and/or
USB 2.0 hubs to perform all those tests.)
</para>
</chapter>
<chapter><title>USB-Standard Types</title>
<para>In <filename>&lt;linux/usb_ch9.h&gt;</filename> you will find
the USB data types defined in chapter 9 of the USB specification.
These data types are used throughout USB, and in APIs including
this host side API, gadget APIs, and usbfs.
</para>
!Iinclude/linux/usb_ch9.h
</chapter>
<chapter><title>Host-Side Data Types and Macros</title>
<para>The host side API exposes several layers to drivers, some of
which are more necessary than others.
These support lifecycle models for host side drivers
and devices, and support passing buffers through usbcore to
some HCD that performs the I/O for the device driver.
</para>
!Iinclude/linux/usb.h
</chapter>
<chapter><title>USB Core APIs</title>
<para>There are two basic I/O models in the USB API.
The most elemental one is asynchronous: drivers submit requests
in the form of an URB, and the URB's completion callback
handle the next step.
All USB transfer types support that model, although there
are special cases for control URBs (which always have setup
and status stages, but may not have a data stage) and
isochronous URBs (which allow large packets and include
per-packet fault reports).
Built on top of that is synchronous API support, where a
driver calls a routine that allocates one or more URBs,
submits them, and waits until they complete.
There are synchronous wrappers for single-buffer control
and bulk transfers (which are awkward to use in some
driver disconnect scenarios), and for scatterlist based
streaming i/o (bulk or interrupt).
</para>
<para>USB drivers need to provide buffers that can be
used for DMA, although they don't necessarily need to
provide the DMA mapping themselves.
There are APIs to use used when allocating DMA buffers,
which can prevent use of bounce buffers on some systems.
In some cases, drivers may be able to rely on 64bit DMA
to eliminate another kind of bounce buffer.
</para>
!Edrivers/usb/core/urb.c
!Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
!Edrivers/usb/core/usb.c
!Edrivers/usb/core/hub.c
</chapter>
<chapter><title>Host Controller APIs</title>
<para>These APIs are only for use by host controller drivers,
most of which implement standard register interfaces such as
EHCI, OHCI, or UHCI.
UHCI was one of the first interfaces, designed by Intel and
also used by VIA; it doesn't do much in hardware.
OHCI was designed later, to have the hardware do more work
(bigger transfers, tracking protocol state, and so on).
EHCI was designed with USB 2.0; its design has features that
resemble OHCI (hardware does much more work) as well as
UHCI (some parts of ISO support, TD list processing).
</para>
<para>There are host controllers other than the "big three",
although most PCI based controllers (and a few non-PCI based
ones) use one of those interfaces.
Not all host controllers use DMA; some use PIO, and there
is also a simulator.
</para>
<para>The same basic APIs are available to drivers for all
those controllers.
For historical reasons they are in two layers:
<structname>struct usb_bus</structname> is a rather thin
layer that became available in the 2.2 kernels, while
<structname>struct usb_hcd</structname> is a more featureful
layer (available in later 2.4 kernels and in 2.5) that
lets HCDs share common code, to shrink driver size
and significantly reduce hcd-specific behaviors.
</para>
!Edrivers/usb/core/hcd.c
!Edrivers/usb/core/hcd-pci.c
!Edrivers/usb/core/buffer.c
</chapter>
<chapter>
<title>The USB Filesystem (usbfs)</title>
<para>This chapter presents the Linux <emphasis>usbfs</emphasis>.
You may prefer to avoid writing new kernel code for your
USB driver; that's the problem that usbfs set out to solve.
User mode device drivers are usually packaged as applications
or libraries, and may use usbfs through some programming library
that wraps it. Such libraries include
<ulink url="http://libusb.sourceforge.net">libusb</ulink>
for C/C++, and
<ulink url="http://jUSB.sourceforge.net">jUSB</ulink> for Java.
</para>
<note><title>Unfinished</title>
<para>This particular documentation is incomplete,
especially with respect to the asynchronous mode.
As of kernel 2.5.66 the code and this (new) documentation
need to be cross-reviewed.
</para>
</note>
<para>Configure usbfs into Linux kernels by enabling the
<emphasis>USB filesystem</emphasis> option (CONFIG_USB_DEVICEFS),
and you get basic support for user mode USB device drivers.
Until relatively recently it was often (confusingly) called
<emphasis>usbdevfs</emphasis> although it wasn't solving what
<emphasis>devfs</emphasis> was.
Every USB device will appear in usbfs, regardless of whether or
not it has a kernel driver; but only devices with kernel drivers
show up in devfs.
</para>
<sect1>
<title>What files are in "usbfs"?</title>
<para>Conventionally mounted at
<filename>/proc/bus/usb</filename>, usbfs
features include:
<itemizedlist>
<listitem><para><filename>/proc/bus/usb/devices</filename>
... a text file
showing each of the USB devices on known to the kernel,
and their configuration descriptors.
You can also poll() this to learn about new devices.
</para></listitem>
<listitem><para><filename>/proc/bus/usb/BBB/DDD</filename>
... magic files
exposing the each device's configuration descriptors, and
supporting a series of ioctls for making device requests,
including I/O to devices. (Purely for access by programs.)
</para></listitem>
</itemizedlist>
</para>
<para> Each bus is given a number (BBB) based on when it was
enumerated; within each bus, each device is given a similar
number (DDD).
Those BBB/DDD paths are not "stable" identifiers;
expect them to change even if you always leave the devices
plugged in to the same hub port.
<emphasis>Don't even think of saving these in application
configuration files.</emphasis>
Stable identifiers are available, for user mode applications
that want to use them. HID and networking devices expose
these stable IDs, so that for example you can be sure that
you told the right UPS to power down its second server.
"usbfs" doesn't (yet) expose those IDs.
</para>
</sect1>
<sect1>
<title>Mounting and Access Control</title>
<para>There are a number of mount options for usbfs, which will
be of most interest to you if you need to override the default
access control policy.
That policy is that only root may read or write device files
(<filename>/proc/bus/BBB/DDD</filename>) although anyone may read
the <filename>devices</filename>
or <filename>drivers</filename> files.
I/O requests to the device also need the CAP_SYS_RAWIO capability,
</para>
<para>The significance of that is that by default, all user mode
device drivers need super-user privileges.
You can change modes or ownership in a driver setup
when the device hotplugs, or maye just start the
driver right then, as a privileged server (or some activity
within one).
That's the most secure approach for multi-user systems,
but for single user systems ("trusted" by that user)
it's more convenient just to grant everyone all access
(using the <emphasis>devmode=0666</emphasis> option)
so the driver can start whenever it's needed.
</para>
<para>The mount options for usbfs, usable in /etc/fstab or
in command line invocations of <emphasis>mount</emphasis>, are:
<variablelist>
<varlistentry>
<term><emphasis>busgid</emphasis>=NNNNN</term>
<listitem><para>Controls the GID used for the
/proc/bus/usb/BBB
directories. (Default: 0)</para></listitem></varlistentry>
<varlistentry><term><emphasis>busmode</emphasis>=MMM</term>
<listitem><para>Controls the file mode used for the
/proc/bus/usb/BBB
directories. (Default: 0555)
</para></listitem></varlistentry>
<varlistentry><term><emphasis>busuid</emphasis>=NNNNN</term>
<listitem><para>Controls the UID used for the
/proc/bus/usb/BBB
directories. (Default: 0)</para></listitem></varlistentry>
<varlistentry><term><emphasis>devgid</emphasis>=NNNNN</term>
<listitem><para>Controls the GID used for the
/proc/bus/usb/BBB/DDD
files. (Default: 0)</para></listitem></varlistentry>
<varlistentry><term><emphasis>devmode</emphasis>=MMM</term>
<listitem><para>Controls the file mode used for the
/proc/bus/usb/BBB/DDD
files. (Default: 0644)</para></listitem></varlistentry>
<varlistentry><term><emphasis>devuid</emphasis>=NNNNN</term>
<listitem><para>Controls the UID used for the
/proc/bus/usb/BBB/DDD
files. (Default: 0)</para></listitem></varlistentry>
<varlistentry><term><emphasis>listgid</emphasis>=NNNNN</term>
<listitem><para>Controls the GID used for the
/proc/bus/usb/devices and drivers files.
(Default: 0)</para></listitem></varlistentry>
<varlistentry><term><emphasis>listmode</emphasis>=MMM</term>
<listitem><para>Controls the file mode used for the
/proc/bus/usb/devices and drivers files.
(Default: 0444)</para></listitem></varlistentry>
<varlistentry><term><emphasis>listuid</emphasis>=NNNNN</term>
<listitem><para>Controls the UID used for the
/proc/bus/usb/devices and drivers files.
(Default: 0)</para></listitem></varlistentry>
</variablelist>
</para>
<para>Note that many Linux distributions hard-wire the mount options
for usbfs in their init scripts, such as
<filename>/etc/rc.d/rc.sysinit</filename>,
rather than making it easy to set this per-system
policy in <filename>/etc/fstab</filename>.
</para>
</sect1>
<sect1>
<title>/proc/bus/usb/devices</title>
<para>This file is handy for status viewing tools in user
mode, which can scan the text format and ignore most of it.
More detailed device status (including class and vendor
status) is available from device-specific files.
For information about the current format of this file,
see the
<filename>Documentation/usb/proc_usb_info.txt</filename>
file in your Linux kernel sources.
</para>
<para>Otherwise the main use for this file from programs
is to poll() it to get notifications of usb devices
as they're plugged or unplugged.
To see what changed, you'd need to read the file and
compare "before" and "after" contents, scan the filesystem,
or see its hotplug event.
</para>
</sect1>
<sect1>
<title>/proc/bus/usb/BBB/DDD</title>
<para>Use these files in one of these basic ways:
</para>
<para><emphasis>They can be read,</emphasis>
producing first the device descriptor
(18 bytes) and then the descriptors for the current configuration.
See the USB 2.0 spec for details about those binary data formats.
You'll need to convert most multibyte values from little endian
format to your native host byte order, although a few of the
fields in the device descriptor (both of the BCD-encoded fields,
and the vendor and product IDs) will be byteswapped for you.
Note that configuration descriptors include descriptors for
interfaces, altsettings, endpoints, and maybe additional
class descriptors.
</para>
<para><emphasis>Perform USB operations</emphasis> using
<emphasis>ioctl()</emphasis> requests to make endpoint I/O
requests (synchronously or asynchronously) or manage
the device.
These requests need the CAP_SYS_RAWIO capability,
as well as filesystem access permissions.
Only one ioctl request can be made on one of these
device files at a time.
This means that if you are synchronously reading an endpoint
from one thread, you won't be able to write to a different
endpoint from another thread until the read completes.
This works for <emphasis>half duplex</emphasis> protocols,
but otherwise you'd use asynchronous i/o requests.
</para>
</sect1>
<sect1>
<title>Life Cycle of User Mode Drivers</title>
<para>Such a driver first needs to find a device file
for a device it knows how to handle.
Maybe it was told about it because a
<filename>/sbin/hotplug</filename> event handling agent
chose that driver to handle the new device.
Or maybe it's an application that scans all the
/proc/bus/usb device files, and ignores most devices.
In either case, it should <function>read()</function> all
the descriptors from the device file,
and check them against what it knows how to handle.
It might just reject everything except a particular
vendor and product ID, or need a more complex policy.
</para>
<para>Never assume there will only be one such device
on the system at a time!
If your code can't handle more than one device at
a time, at least detect when there's more than one, and
have your users choose which device to use.
</para>
<para>Once your user mode driver knows what device to use,
it interacts with it in either of two styles.
The simple style is to make only control requests; some
devices don't need more complex interactions than those.
(An example might be software using vendor-specific control
requests for some initialization or configuration tasks,
with a kernel driver for the rest.)
</para>
<para>More likely, you need a more complex style driver:
one using non-control endpoints, reading or writing data
and claiming exclusive use of an interface.
<emphasis>Bulk</emphasis> transfers are easiest to use,
but only their sibling <emphasis>interrupt</emphasis> transfers
work with low speed devices.
Both interrupt and <emphasis>isochronous</emphasis> transfers
offer service guarantees because their bandwidth is reserved.
Such "periodic" transfers are awkward to use through usbfs,
unless you're using the asynchronous calls. However, interrupt
transfers can also be used in a synchronous "one shot" style.
</para>
<para>Your user-mode driver should never need to worry
about cleaning up request state when the device is
disconnected, although it should close its open file
descriptors as soon as it starts seeing the ENODEV
errors.
</para>
</sect1>
<sect1><title>The ioctl() Requests</title>
<para>To use these ioctls, you need to include the following
headers in your userspace program:
<programlisting>#include &lt;linux/usb.h&gt;
#include &lt;linux/usbdevice_fs.h&gt;
#include &lt;asm/byteorder.h&gt;</programlisting>
The standard USB device model requests, from "Chapter 9" of
the USB 2.0 specification, are automatically included from
the <filename>&lt;linux/usb_ch9.h&gt;</filename> header.
</para>
<para>Unless noted otherwise, the ioctl requests
described here will
update the modification time on the usbfs file to which
they are applied (unless they fail).
A return of zero indicates success; otherwise, a
standard USB error code is returned. (These are
documented in
<filename>Documentation/usb/error-codes.txt</filename>
in your kernel sources.)
</para>
<para>Each of these files multiplexes access to several
I/O streams, one per endpoint.
Each device has one control endpoint (endpoint zero)
which supports a limited RPC style RPC access.
Devices are configured
by khubd (in the kernel) setting a device-wide
<emphasis>configuration</emphasis> that affects things
like power consumption and basic functionality.
The endpoints are part of USB <emphasis>interfaces</emphasis>,
which may have <emphasis>altsettings</emphasis>
affecting things like which endpoints are available.
Many devices only have a single configuration and interface,
so drivers for them will ignore configurations and altsettings.
</para>
<sect2>
<title>Management/Status Requests</title>
<para>A number of usbfs requests don't deal very directly
with device I/O.
They mostly relate to device management and status.
These are all synchronous requests.
</para>
<variablelist>
<varlistentry><term>USBDEVFS_CLAIMINTERFACE</term>
<listitem><para>This is used to force usbfs to
claim a specific interface,
which has not previously been claimed by usbfs or any other
kernel driver.
The ioctl parameter is an integer holding the number of
the interface (bInterfaceNumber from descriptor).
</para><para>
Note that if your driver doesn't claim an interface
before trying to use one of its endpoints, and no
other driver has bound to it, then the interface is
automatically claimed by usbfs.
</para><para>
This claim will be released by a RELEASEINTERFACE ioctl,
or by closing the file descriptor.
File modification time is not updated by this request.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_CONNECTINFO</term>
<listitem><para>Says whether the device is lowspeed.
The ioctl parameter points to a structure like this:
<programlisting>struct usbdevfs_connectinfo {
unsigned int devnum;
unsigned char slow;
}; </programlisting>
File modification time is not updated by this request.
</para><para>
<emphasis>You can't tell whether a "not slow"
device is connected at high speed (480 MBit/sec)
or just full speed (12 MBit/sec).</emphasis>
You should know the devnum value already,
it's the DDD value of the device file name.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_GETDRIVER</term>
<listitem><para>Returns the name of the kernel driver
bound to a given interface (a string). Parameter
is a pointer to this structure, which is modified:
<programlisting>struct usbdevfs_getdriver {
unsigned int interface;
char driver[USBDEVFS_MAXDRIVERNAME + 1];
};</programlisting>
File modification time is not updated by this request.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_IOCTL</term>
<listitem><para>Passes a request from userspace through
to a kernel driver that has an ioctl entry in the
<emphasis>struct usb_driver</emphasis> it registered.
<programlisting>struct usbdevfs_ioctl {
int ifno;
int ioctl_code;
void *data;
};
/* user mode call looks like this.
* 'request' becomes the driver->ioctl() 'code' parameter.
* the size of 'param' is encoded in 'request', and that data
* is copied to or from the driver->ioctl() 'buf' parameter.
*/
static int
usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
{
struct usbdevfs_ioctl wrapper;
wrapper.ifno = ifno;
wrapper.ioctl_code = request;
wrapper.data = param;
return ioctl (fd, USBDEVFS_IOCTL, &amp;wrapper);
} </programlisting>
File modification time is not updated by this request.
</para><para>
This request lets kernel drivers talk to user mode code
through filesystem operations even when they don't create
a charactor or block special device.
It's also been used to do things like ask devices what
device special file should be used.
Two pre-defined ioctls are used
to disconnect and reconnect kernel drivers, so
that user mode code can completely manage binding
and configuration of devices.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_RELEASEINTERFACE</term>
<listitem><para>This is used to release the claim usbfs
made on interface, either implicitly or because of a
USBDEVFS_CLAIMINTERFACE call, before the file
descriptor is closed.
The ioctl parameter is an integer holding the number of
the interface (bInterfaceNumber from descriptor);
File modification time is not updated by this request.
</para><warning><para>
<emphasis>No security check is made to ensure
that the task which made the claim is the one
which is releasing it.
This means that user mode driver may interfere
other ones. </emphasis>
</para></warning></listitem></varlistentry>
<varlistentry><term>USBDEVFS_RESETEP</term>
<listitem><para>Resets the data toggle value for an endpoint
(bulk or interrupt) to DATA0.
The ioctl parameter is an integer endpoint number
(1 to 15, as identified in the endpoint descriptor),
with USB_DIR_IN added if the device's endpoint sends
data to the host.
</para><warning><para>
<emphasis>Avoid using this request.
It should probably be removed.</emphasis>
Using it typically means the device and driver will lose
toggle synchronization. If you really lost synchronization,
you likely need to completely handshake with the device,
using a request like CLEAR_HALT
or SET_INTERFACE.
</para></warning></listitem></varlistentry>
</variablelist>
</sect2>
<sect2>
<title>Synchronous I/O Support</title>
<para>Synchronous requests involve the kernel blocking
until until the user mode request completes, either by
finishing successfully or by reporting an error.
In most cases this is the simplest way to use usbfs,
although as noted above it does prevent performing I/O
to more than one endpoint at a time.
</para>
<variablelist>
<varlistentry><term>USBDEVFS_BULK</term>
<listitem><para>Issues a bulk read or write request to the
device.
The ioctl parameter is a pointer to this structure:
<programlisting>struct usbdevfs_bulktransfer {
unsigned int ep;
unsigned int len;
unsigned int timeout; /* in milliseconds */
void *data;
};</programlisting>
</para><para>The "ep" value identifies a
bulk endpoint number (1 to 15, as identified in an endpoint
descriptor),
masked with USB_DIR_IN when referring to an endpoint which
sends data to the host from the device.
The length of the data buffer is identified by "len";
Recent kernels support requests up to about 128KBytes.
<emphasis>FIXME say how read length is returned,
and how short reads are handled.</emphasis>.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_CLEAR_HALT</term>
<listitem><para>Clears endpoint halt (stall) and
resets the endpoint toggle. This is only
meaningful for bulk or interrupt endpoints.
The ioctl parameter is an integer endpoint number
(1 to 15, as identified in an endpoint descriptor),
masked with USB_DIR_IN when referring to an endpoint which
sends data to the host from the device.
</para><para>
Use this on bulk or interrupt endpoints which have
stalled, returning <emphasis>-EPIPE</emphasis> status
to a data transfer request.
Do not issue the control request directly, since
that could invalidate the host's record of the
data toggle.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_CONTROL</term>
<listitem><para>Issues a control request to the device.
The ioctl parameter points to a structure like this:
<programlisting>struct usbdevfs_ctrltransfer {
__u8 bRequestType;
__u8 bRequest;
__u16 wValue;
__u16 wIndex;
__u16 wLength;
__u32 timeout; /* in milliseconds */
void *data;
};</programlisting>
</para><para>
The first eight bytes of this structure are the contents
of the SETUP packet to be sent to the device; see the
USB 2.0 specification for details.
The bRequestType value is composed by combining a
USB_TYPE_* value, a USB_DIR_* value, and a
USB_RECIP_* value (from
<emphasis>&lt;linux/usb.h&gt;</emphasis>).
If wLength is nonzero, it describes the length of the data
buffer, which is either written to the device
(USB_DIR_OUT) or read from the device (USB_DIR_IN).
</para><para>
At this writing, you can't transfer more than 4 KBytes
of data to or from a device; usbfs has a limit, and
some host controller drivers have a limit.
(That's not usually a problem.)
<emphasis>Also</emphasis> there's no way to say it's
not OK to get a short read back from the device.
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_RESET</term>
<listitem><para>Does a USB level device reset.
The ioctl parameter is ignored.
After the reset, this rebinds all device interfaces.
File modification time is not updated by this request.
</para><warning><para>
<emphasis>Avoid using this call</emphasis>
until some usbcore bugs get fixed,
since it does not fully synchronize device, interface,
and driver (not just usbfs) state.
</para></warning></listitem></varlistentry>
<varlistentry><term>USBDEVFS_SETINTERFACE</term>
<listitem><para>Sets the alternate setting for an
interface. The ioctl parameter is a pointer to a
structure like this:
<programlisting>struct usbdevfs_setinterface {
unsigned int interface;
unsigned int altsetting;
}; </programlisting>
File modification time is not updated by this request.
</para><para>
Those struct members are from some interface descriptor
applying to the the current configuration.
The interface number is the bInterfaceNumber value, and
the altsetting number is the bAlternateSetting value.
(This resets each endpoint in the interface.)
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_SETCONFIGURATION</term>
<listitem><para>Issues the
<function>usb_set_configuration</function> call
for the device.
The parameter is an integer holding the number of
a configuration (bConfigurationValue from descriptor).
File modification time is not updated by this request.
</para><warning><para>
<emphasis>Avoid using this call</emphasis>
until some usbcore bugs get fixed,
since it does not fully synchronize device, interface,
and driver (not just usbfs) state.
</para></warning></listitem></varlistentry>
</variablelist>
</sect2>
<sect2>
<title>Asynchronous I/O Support</title>
<para>As mentioned above, there are situations where it may be
important to initiate concurrent operations from user mode code.
This is particularly important for periodic transfers
(interrupt and isochronous), but it can be used for other
kinds of USB requests too.
In such cases, the asynchronous requests described here
are essential. Rather than submitting one request and having
the kernel block until it completes, the blocking is separate.
</para>
<para>These requests are packaged into a structure that
resembles the URB used by kernel device drivers.
(No POSIX Async I/O support here, sorry.)
It identifies the endpoint type (USBDEVFS_URB_TYPE_*),
endpoint (number, masked with USB_DIR_IN as appropriate),
buffer and length, and a user "context" value serving to
uniquely identify each request.
(It's usually a pointer to per-request data.)
Flags can modify requests (not as many as supported for
kernel drivers).
</para>
<para>Each request can specify a realtime signal number
(between SIGRTMIN and SIGRTMAX, inclusive) to request a
signal be sent when the request completes.
</para>
<para>When usbfs returns these urbs, the status value
is updated, and the buffer may have been modified.
Except for isochronous transfers, the actual_length is
updated to say how many bytes were transferred; if the
USBDEVFS_URB_DISABLE_SPD flag is set
("short packets are not OK"), if fewer bytes were read
than were requested then you get an error report.
</para>
<programlisting>struct usbdevfs_iso_packet_desc {
unsigned int length;
unsigned int actual_length;
unsigned int status;
};
struct usbdevfs_urb {
unsigned char type;
unsigned char endpoint;
int status;
unsigned int flags;
void *buffer;
int buffer_length;
int actual_length;
int start_frame;
int number_of_packets;
int error_count;
unsigned int signr;
void *usercontext;
struct usbdevfs_iso_packet_desc iso_frame_desc[];
};</programlisting>
<para> For these asynchronous requests, the file modification
time reflects when the request was initiated.
This contrasts with their use with the synchronous requests,
where it reflects when requests complete.
</para>
<variablelist>
<varlistentry><term>USBDEVFS_DISCARDURB</term>
<listitem><para>
<emphasis>TBS</emphasis>
File modification time is not updated by this request.
</para><para>
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_DISCSIGNAL</term>
<listitem><para>
<emphasis>TBS</emphasis>
File modification time is not updated by this request.
</para><para>
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_REAPURB</term>
<listitem><para>
<emphasis>TBS</emphasis>
File modification time is not updated by this request.
</para><para>
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_REAPURBNDELAY</term>
<listitem><para>
<emphasis>TBS</emphasis>
File modification time is not updated by this request.
</para><para>
</para></listitem></varlistentry>
<varlistentry><term>USBDEVFS_SUBMITURB</term>
<listitem><para>
<emphasis>TBS</emphasis>
</para><para>
</para></listitem></varlistentry>
</variablelist>
</sect2>
</sect1>
</chapter>
</book>
<!-- vim:syntax=sgml:sw=4
-->

View File

@@ -0,0 +1,597 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="ViaAudioGuide">
<bookinfo>
<title>Via 686 Audio Driver for Linux</title>
<authorgroup>
<author>
<firstname>Jeff</firstname>
<surname>Garzik</surname>
</author>
</authorgroup>
<copyright>
<year>1999-2001</year>
<holder>Jeff Garzik</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The Via VT82C686A "super southbridge" chips contain
AC97-compatible audio logic which features dual 16-bit stereo
PCM sound channels (full duplex), plus a third PCM channel intended for use
in hardware-assisted FM synthesis.
</para>
<para>
The current Linux kernel audio driver for this family of chips
supports audio playback and recording, but hardware-assisted
FM features, and hardware buffer direct-access (mmap)
support are not yet available.
</para>
<para>
This driver supports any Linux kernel version after 2.4.10.
</para>
<para>
Please send bug reports to the mailing list <email>linux-via@gtf.org</email>.
To subscribe, e-mail <email>majordomo@gtf.org</email> with
</para>
<programlisting>
subscribe linux-via
</programlisting>
<para>
in the body of the message.
</para>
</chapter>
<chapter id="install">
<title>Driver Installation</title>
<para>
To use this audio driver, select the
CONFIG_SOUND_VIA82CXXX option in the section Sound during kernel configuration.
Follow the usual kernel procedures for rebuilding the kernel,
or building and installing driver modules.
</para>
<para>
To make this driver the default audio driver, you can add the
following to your /etc/conf.modules file:
</para>
<programlisting>
alias sound via82cxxx_audio
</programlisting>
<para>
Note that soundcore and ac97_codec support modules
are also required for working audio, in addition to
the via82cxxx_audio module itself.
</para>
</chapter>
<chapter id="reportbug">
<title>Submitting a bug report</title>
<sect1 id="bugrepdesc"><title>Description of problem</title>
<para>
Describe the application you were using to play/record sound, and how
to reproduce the problem.
</para>
</sect1>
<sect1 id="bugrepdiag"><title>Diagnostic output</title>
<para>
Obtain the via-audio-diag diagnostics program from
http://sf.net/projects/gkernel/ and provide a dump of the
audio chip's registers while the problem is occurring. Sample command line:
</para>
<programlisting>
./via-audio-diag -aps > diag-output.txt
</programlisting>
</sect1>
<sect1 id="bugrepdebug"><title>Driver debug output</title>
<para>
Define <constant>VIA_DEBUG</constant> at the beginning of the driver, then capture and email
the kernel log output. This can be viewed in the system kernel log (if
enabled), or via the dmesg program. Sample command line:
</para>
<programlisting>
dmesg > /tmp/dmesg-output.txt
</programlisting>
</sect1>
<sect1 id="bugrepprintk"><title>Bigger kernel message buffer</title>
<para>
If you wish to increase the size of the buffer displayed by dmesg, then
change the <constant>LOG_BUF_LEN</constant> macro at the top of linux/kernel/printk.c, recompile
your kernel, and pass the <constant>LOG_BUF_LEN</constant> value to dmesg. Sample command line with
<constant>LOG_BUF_LEN</constant> == 32768:
</para>
<programlisting>
dmesg -s 32768 > /tmp/dmesg-output.txt
</programlisting>
</sect1>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
<variablelist>
<varlistentry><term>Low volume</term>
<listitem>
<para>
Volume too low on many systems. Workaround: use mixer program
such as xmixer to increase volume.
</para>
</listitem></varlistentry>
</variablelist>
</para>
</chapter>
<chapter id="thanks">
<title>Thanks</title>
<para>
Via for providing e-mail support, specs, and NDA'd source code.
</para>
<para>
MandrakeSoft for providing hacking time.
</para>
<para>
AC97 mixer interface fixes and debugging by Ron Cemer <email>roncemer@gte.net</email>.
</para>
<para>
Rui Sousa <email>rui.sousa@conexant.com</email>, for bugfixing
MMAP support, and several other notable fixes that resulted from
his hard work and testing.
</para>
<para>
Adrian Cox <email>adrian@humboldt.co.uk</email>, for bugfixing
MMAP support, and several other notable fixes that resulted from
his hard work and testing.
</para>
<para>
Thomas Sailer for further bugfixes.
</para>
</chapter>
<chapter id="notes">
<title>Random Notes</title>
<para>
Two /proc pseudo-files provide diagnostic information. This is generally
not useful to most users. Power users can disable CONFIG_SOUND_VIA82CXXX_PROCFS,
and remove the /proc support code. Once
version 2.0.0 is released, the /proc support code will be disabled by
default. Available /proc pseudo-files:
</para>
<programlisting>
/proc/driver/via/0/info
/proc/driver/via/0/ac97
</programlisting>
<para>
This driver by default supports all PCI audio devices which report
a vendor id of 0x1106, and a device id of 0x3058. Subsystem vendor
and device ids are not examined.
</para>
<para>
GNU indent formatting options:
<programlisting>
-kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl
</programlisting>
</para>
<para>
Via has graciously donated e-mail support and source code to help further
the development of this driver. Their assistance has been invaluable
in the design and coding of the next major version of this driver.
</para>
<para>
The Via audio chip apparently provides a second PCM scatter-gather
DMA channel just for FM data, but does not have a full hardware MIDI
processor. I haven't put much thought towards a solution here, but it
might involve using SoftOSS midi wave table, or simply disabling MIDI
support altogether and using the FM PCM channel as a second (input? output?)
</para>
</chapter>
<chapter id="changelog">
<title>Driver ChangeLog</title>
<sect1 id="version191"><title>
Version 1.9.1
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
DSP read/write bugfixes from Thomas Sailer.
</para>
</listitem>
<listitem>
<para>
Add new PCI id for single-channel use of Via 8233.
</para>
</listitem>
<listitem>
<para>
Other bug fixes, tweaks, new ioctls.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version1115"><title>
Version 1.1.15
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Support for variable fragment size and variable fragment number (Rui
Sousa)
</para>
</listitem>
<listitem>
<para>
Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &amp;
write mode (Rui Sousa)
</para>
</listitem>
<listitem>
<para>
Mmaped sound is now fully functional. (Rui Sousa)
</para>
</listitem>
<listitem>
<para>
Make sure to enable PCI device before reading any of its PCI
config information. (fixes potential hotplug problems)
</para>
</listitem>
<listitem>
<para>
Clean up code a bit and add more internal function documentation.
</para>
</listitem>
<listitem>
<para>
AC97 codec access fixes (Adrian Cox)
</para>
</listitem>
<listitem>
<para>
Big endian fixes (Adrian Cox)
</para>
</listitem>
<listitem>
<para>
MIDI support (Adrian Cox)
</para>
</listitem>
<listitem>
<para>
Detect and report locked-rate AC97 codecs. If your hardware only
supports 48Khz (locked rate), then your recording/playback software
must upsample or downsample accordingly. The hardware cannot do it.
</para>
</listitem>
<listitem>
<para>
Use new pci_request_regions and pci_disable_device functions in
kernel 2.4.6.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version1114"><title>
Version 1.1.14
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Use VM_RESERVE when available, to eliminate unnecessary page faults.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version1112"><title>
Version 1.1.12
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
mmap bug fixes from Linus.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version1111"><title>
Version 1.1.11
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Many more bug fixes. mmap enabled by default, but may still be buggy.
</para>
</listitem>
<listitem>
<para>
Uses new and spiffy method of mmap'ing the DMA buffer, based
on a suggestion from Linus.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version1110"><title>
Version 1.1.10
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Many bug fixes. mmap enabled by default, but may still be buggy.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version119"><title>
Version 1.1.9
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Redesign and rewrite audio playback implementation. (faster and smaller, hopefully)
</para>
</listitem>
<listitem>
<para>
Implement recording and full duplex (DSP_CAP_DUPLEX) support.
</para>
</listitem>
<listitem>
<para>
Make procfs support optional.
</para>
</listitem>
<listitem>
<para>
Quick interrupt status check, to lessen overhead in interrupt
sharing situations.
</para>
</listitem>
<listitem>
<para>
Add mmap(2) support. Disabled for now, it is still buggy and experimental.
</para>
</listitem>
<listitem>
<para>
Surround all syscalls with a semaphore for cheap and easy SMP protection.
</para>
</listitem>
<listitem>
<para>
Fix bug in channel shutdown (hardware channel reset) code.
</para>
</listitem>
<listitem>
<para>
Remove unnecessary spinlocks (better performance).
</para>
</listitem>
<listitem>
<para>
Eliminate "unknown AFMT" message by using a different method
of selecting the best AFMT_xxx sound sample format for use.
</para>
</listitem>
<listitem>
<para>
Support for realtime hardware pointer position reporting
(DSP_CAP_REALTIME, SNDCTL_DSP_GETxPTR ioctls)
</para>
</listitem>
<listitem>
<para>
Support for capture/playback triggering
(DSP_CAP_TRIGGER, SNDCTL_DSP_SETTRIGGER ioctls)
</para>
</listitem>
<listitem>
<para>
SNDCTL_DSP_SETDUPLEX and SNDCTL_DSP_POST ioctls now handled.
</para>
</listitem>
<listitem>
<para>
Rewrite open(2) and close(2) logic to allow only one user at
a time. All other open(2) attempts will sleep until they succeed.
FIXME: open(O_RDONLY) and open(O_WRONLY) should be allowed to succeed.
</para>
</listitem>
<listitem>
<para>
Reviewed code to ensure that SMP and multiple audio devices
are fully supported.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version118"><title>
Version 1.1.8
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Clean up interrupt handler output. Fixes the following kernel error message:
</para>
<programlisting>
unhandled interrupt ...
</programlisting>
</listitem>
<listitem>
<para>
Convert documentation to DocBook, so that PDF, HTML and PostScript (.ps) output is readily
available.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version117"><title>
Version 1.1.7
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Fix module unload bug where mixer device left registered
after driver exit
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version116"><title>
Version 1.1.6
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Rewrite via_set_rate to mimic ALSA basic AC97 rate setting
</para>
</listitem>
<listitem>
<para>
Remove much dead code
</para>
</listitem>
<listitem>
<para>
Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
</para>
</listitem>
<listitem>
<para>
Fix build problem in via_dsp_ioctl
</para>
</listitem>
<listitem>
<para>
Optimize included headers to eliminate headers found in linux/sound
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version115"><title>
Version 1.1.5
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Disable some overly-verbose debugging code
</para>
</listitem>
<listitem>
<para>
Remove unnecessary sound locks
</para>
</listitem>
<listitem>
<para>
Fix some ioctls for better time resolution
</para>
</listitem>
<listitem>
<para>
Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="version114"><title>
Version 1.1.4
</title>
<itemizedlist spacing="compact">
<listitem>
<para>
Completed rewrite of driver. Eliminated SoundBlaster compatibility
completely, and now uses the much-faster scatter-gather DMA engine.
</para>
</listitem>
</itemizedlist>
</sect1>
</chapter>
<chapter id="intfunctions">
<title>Internal Functions</title>
!Isound/oss/via82cxxx_audio.c
</chapter>
</book>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="WANGuide">
<bookinfo>
<title>Synchronous PPP and Cisco HDLC Programming Guide</title>
<authorgroup>
<author>
<firstname>Alan</firstname>
<surname>Cox</surname>
<affiliation>
<address>
<email>alan@redhat.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2000</year>
<holder>Alan Cox</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The syncppp drivers in Linux provide a fairly complete
implementation of Cisco HDLC and a minimal implementation of
PPP. The longer term goal is to switch the PPP layer to the
generic PPP interface that is new in Linux 2.3.x. The API should
remain unchanged when this is done, but support will then be
available for IPX, compression and other PPP features
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
<variablelist>
<varlistentry><term>PPP is minimal</term>
<listitem>
<para>
The current PPP implementation is very basic, although sufficient
for most wan usages.
</para>
</listitem></varlistentry>
<varlistentry><term>Cisco HDLC Quirks</term>
<listitem>
<para>
Currently we do not end all packets with the correct Cisco multicast
or unicast flags. Nothing appears to mind too much but this should
be corrected.
</para>
</listitem></varlistentry>
</variablelist>
</para>
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Edrivers/net/wan/syncppp.c
</chapter>
</book>

View File

@@ -0,0 +1,419 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="USBDeviceDriver">
<bookinfo>
<title>Writing USB Device Drivers</title>
<authorgroup>
<author>
<firstname>Greg</firstname>
<surname>Kroah-Hartman</surname>
<affiliation>
<address>
<email>greg@kroah.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2001-2002</year>
<holder>Greg Kroah-Hartman</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
<para>
This documentation is based on an article published in
Linux Journal Magazine, October 2001, Issue 90.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The Linux USB subsystem has grown from supporting only two different
types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
different types of devices in the 2.4 kernel. Linux currently supports
almost all USB class devices (standard types of devices like keyboards,
mice, modems, printers and speakers) and an ever-growing number of
vendor-specific devices (such as USB to serial converters, digital
cameras, Ethernet devices and MP3 players). For a full list of the
different USB devices currently supported, see Resources.
</para>
<para>
The remaining kinds of USB devices that do not have support on Linux are
almost all vendor-specific devices. Each vendor decides to implement a
custom protocol to talk to their device, so a custom driver usually needs
to be created. Some vendors are open with their USB protocols and help
with the creation of Linux drivers, while others do not publish them, and
developers are forced to reverse-engineer. See Resources for some links
to handy reverse-engineering tools.
</para>
<para>
Because each different protocol causes a new driver to be created, I have
written a generic USB driver skeleton, modeled after the pci-skeleton.c
file in the kernel source tree upon which many PCI network drivers have
been based. This USB skeleton can be found at drivers/usb/usb-skeleton.c
in the kernel source tree. In this article I will walk through the basics
of the skeleton driver, explaining the different pieces and what needs to
be done to customize it to your specific device.
</para>
</chapter>
<chapter id="basics">
<title>Linux USB Basics</title>
<para>
If you are going to write a Linux USB driver, please become familiar with
the USB protocol specification. It can be found, along with many other
useful documents, at the USB home page (see Resources). An excellent
introduction to the Linux USB subsystem can be found at the USB Working
Devices List (see Resources). It explains how the Linux USB subsystem is
structured and introduces the reader to the concept of USB urbs, which
are essential to USB drivers.
</para>
<para>
The first thing a Linux USB driver needs to do is register itself with
the Linux USB subsystem, giving it some information about which devices
the driver supports and which functions to call when a device supported
by the driver is inserted or removed from the system. All of this
information is passed to the USB subsystem in the usb_driver structure.
The skeleton driver declares a usb_driver as:
</para>
<programlisting>
static struct usb_driver skel_driver = {
.name = "skeleton",
.probe = skel_probe,
.disconnect = skel_disconnect,
.fops = &amp;skel_fops,
.minor = USB_SKEL_MINOR_BASE,
.id_table = skel_table,
};
</programlisting>
<para>
The variable name is a string that describes the driver. It is used in
informational messages printed to the system log. The probe and
disconnect function pointers are called when a device that matches the
information provided in the id_table variable is either seen or removed.
</para>
<para>
The fops and minor variables are optional. Most USB drivers hook into
another kernel subsystem, such as the SCSI, network or TTY subsystem.
These types of drivers register themselves with the other kernel
subsystem, and any user-space interactions are provided through that
interface. But for drivers that do not have a matching kernel subsystem,
such as MP3 players or scanners, a method of interacting with user space
is needed. The USB subsystem provides a way to register a minor device
number and a set of file_operations function pointers that enable this
user-space interaction. The skeleton driver needs this kind of interface,
so it provides a minor starting number and a pointer to its
file_operations functions.
</para>
<para>
The USB driver is then registered with a call to usb_register, usually in
the driver's init function, as shown here:
</para>
<programlisting>
static int __init usb_skel_init(void)
{
int result;
/* register this driver with the USB subsystem */
result = usb_register(&amp;skel_driver);
if (result &lt; 0) {
err(&quot;usb_register failed for the &quot;__FILE__ &quot;driver.&quot;
&quot;Error number %d&quot;, result);
return -1;
}
return 0;
}
module_init(usb_skel_init);
</programlisting>
<para>
When the driver is unloaded from the system, it needs to unregister
itself with the USB subsystem. This is done with the usb_unregister
function:
</para>
<programlisting>
static void __exit usb_skel_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&amp;skel_driver);
}
module_exit(usb_skel_exit);
</programlisting>
<para>
To enable the linux-hotplug system to load the driver automatically when
the device is plugged in, you need to create a MODULE_DEVICE_TABLE. The
following code tells the hotplug scripts that this module supports a
single device with a specific vendor and product ID:
</para>
<programlisting>
/* table of devices that work with this driver */
static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, skel_table);
</programlisting>
<para>
There are other macros that can be used in describing a usb_device_id for
drivers that support a whole class of USB drivers. See usb.h for more
information on this.
</para>
</chapter>
<chapter id="device">
<title>Device operation</title>
<para>
When a device is plugged into the USB bus that matches the device ID
pattern that your driver registered with the USB core, the probe function
is called. The usb_device structure, interface number and the interface ID
are passed to the function:
</para>
<programlisting>
static int skel_probe(struct usb_interface *interface,
const struct usb_device_id *id)
</programlisting>
<para>
The driver now needs to verify that this device is actually one that it
can accept. If so, it returns 0.
If not, or if any error occurs during initialization, an errorcode
(such as <literal>-ENOMEM</literal> or <literal>-ENODEV</literal>)
is returned from the probe function.
</para>
<para>
In the skeleton driver, we determine what end points are marked as bulk-in
and bulk-out. We create buffers to hold the data that will be sent and
received from the device, and a USB urb to write data to the device is
initialized.
</para>
<para>
Conversely, when the device is removed from the USB bus, the disconnect
function is called with the device pointer. The driver needs to clean any
private data that has been allocated at this time and to shut down any
pending urbs that are in the USB system. The driver also unregisters
itself from the devfs subsystem with the call:
</para>
<programlisting>
/* remove our devfs node */
devfs_unregister(skel->devfs);
</programlisting>
<para>
Now that the device is plugged into the system and the driver is bound to
the device, any of the functions in the file_operations structure that
were passed to the USB subsystem will be called from a user program trying
to talk to the device. The first function called will be open, as the
program tries to open the device for I/O. We increment our private usage
count and save off a pointer to our internal structure in the file
structure. This is done so that future calls to file operations will
enable the driver to determine which device the user is addressing. All
of this is done with the following code:
</para>
<programlisting>
/* increment our usage count for the module */
++skel->open_count;
/* save our object in the file's private structure */
file->private_data = dev;
</programlisting>
<para>
After the open function is called, the read and write functions are called
to receive and send data to the device. In the skel_write function, we
receive a pointer to some data that the user wants to send to the device
and the size of the data. The function determines how much data it can
send to the device based on the size of the write urb it has created (this
size depends on the size of the bulk out end point that the device has).
Then it copies the data from user space to kernel space, points the urb to
the data and submits the urb to the USB subsystem. This can be shown in
he following code:
</para>
<programlisting>
/* we can only write as much as 1 urb will hold */
bytes_written = (count > skel->bulk_out_size) ? skel->bulk_out_size : count;
/* copy the data from user space into our urb */
copy_from_user(skel->write_urb->transfer_buffer, buffer, bytes_written);
/* set up our urb */
usb_fill_bulk_urb(skel->write_urb,
skel->dev,
usb_sndbulkpipe(skel->dev, skel->bulk_out_endpointAddr),
skel->write_urb->transfer_buffer,
bytes_written,
skel_write_bulk_callback,
skel);
/* send the data out the bulk port */
result = usb_submit_urb(skel->write_urb);
if (result) {
err(&quot;Failed submitting write urb, error %d&quot;, result);
}
</programlisting>
<para>
When the write urb is filled up with the proper information using the
usb_fill_bulk_urb function, we point the urb's completion callback to call our
own skel_write_bulk_callback function. This function is called when the
urb is finished by the USB subsystem. The callback function is called in
interrupt context, so caution must be taken not to do very much processing
at that time. Our implementation of skel_write_bulk_callback merely
reports if the urb was completed successfully or not and then returns.
</para>
<para>
The read function works a bit differently from the write function in that
we do not use an urb to transfer data from the device to the driver.
Instead we call the usb_bulk_msg function, which can be used to send or
receive data from a device without having to create urbs and handle
urb completion callback functions. We call the usb_bulk_msg function,
giving it a buffer into which to place any data received from the device
and a timeout value. If the timeout period expires without receiving any
data from the device, the function will fail and return an error message.
This can be shown with the following code:
</para>
<programlisting>
/* do an immediate bulk read to get data from the device */
retval = usb_bulk_msg (skel->dev,
usb_rcvbulkpipe (skel->dev,
skel->bulk_in_endpointAddr),
skel->bulk_in_buffer,
skel->bulk_in_size,
&amp;count, HZ*10);
/* if the read was successful, copy the data to user space */
if (!retval) {
if (copy_to_user (buffer, skel->bulk_in_buffer, count))
retval = -EFAULT;
else
retval = count;
}
</programlisting>
<para>
The usb_bulk_msg function can be very useful for doing single reads or
writes to a device; however, if you need to read or write constantly to a
device, it is recommended to set up your own urbs and submit them to the
USB subsystem.
</para>
<para>
When the user program releases the file handle that it has been using to
talk to the device, the release function in the driver is called. In this
function we decrement our private usage count and wait for possible
pending writes:
</para>
<programlisting>
/* decrement our usage count for the device */
--skel->open_count;
</programlisting>
<para>
One of the more difficult problems that USB drivers must be able to handle
smoothly is the fact that the USB device may be removed from the system at
any point in time, even if a program is currently talking to it. It needs
to be able to shut down any current reads and writes and notify the
user-space programs that the device is no longer there. The following
code (function <function>skel_delete</function>)
is an example of how to do this: </para>
<programlisting>
static inline void skel_delete (struct usb_skel *dev)
{
if (dev->bulk_in_buffer != NULL)
kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL)
usb_buffer_free (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer,
dev->write_urb->transfer_dma);
if (dev->write_urb != NULL)
usb_free_urb (dev->write_urb);
kfree (dev);
}
</programlisting>
<para>
If a program currently has an open handle to the device, we reset the flag
<literal>device_present</literal>. For
every read, write, release and other functions that expect a device to be
present, the driver first checks this flag to see if the device is
still present. If not, it releases that the device has disappeared, and a
-ENODEV error is returned to the user-space program. When the release
function is eventually called, it determines if there is no device
and if not, it does the cleanup that the skel_disconnect
function normally does if there are no open files on the device (see
Listing 5).
</para>
</chapter>
<chapter id="iso">
<title>Isochronous Data</title>
<para>
This usb-skeleton driver does not have any examples of interrupt or
isochronous data being sent to or from the device. Interrupt data is sent
almost exactly as bulk data is, with a few minor exceptions. Isochronous
data works differently with continuous streams of data being sent to or
from the device. The audio and video camera drivers are very good examples
of drivers that handle isochronous data and will be useful if you also
need to do this.
</para>
</chapter>
<chapter id="Conclusion">
<title>Conclusion</title>
<para>
Writing Linux USB device drivers is not a difficult task as the
usb-skeleton driver shows. This driver, combined with the other current
USB drivers, should provide enough examples to help a beginning author
create a working driver in a minimal amount of time. The linux-usb-devel
mailing list archives also contain a lot of helpful information.
</para>
</chapter>
<chapter id="resources">
<title>Resources</title>
<para>
The Linux USB Project: <ulink url="http://www.linux-usb.org">http://www.linux-usb.org/</ulink>
</para>
<para>
Linux Hotplug Project: <ulink url="http://linux-hotplug.sourceforge.net">http://linux-hotplug.sourceforge.net/</ulink>
</para>
<para>
Linux USB Working Devices List: <ulink url="http://www.qbik.ch/usb/devices">http://www.qbik.ch/usb/devices/</ulink>
</para>
<para>
linux-usb-devel Mailing List Archives: <ulink url="http://marc.theaimsgroup.com/?l=linux-usb-devel">http://marc.theaimsgroup.com/?l=linux-usb-devel</ulink>
</para>
<para>
Programming Guide for Linux USB Device Drivers: <ulink url="http://usb.cs.tum.edu/usbdoc">http://usb.cs.tum.edu/usbdoc</ulink>
</para>
<para>
USB Home Page: <ulink url="http://www.usb.org">http://www.usb.org</ulink>
</para>
</chapter>
</book>

View File

@@ -0,0 +1,385 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="Z85230Guide">
<bookinfo>
<title>Z8530 Programming Guide</title>
<authorgroup>
<author>
<firstname>Alan</firstname>
<surname>Cox</surname>
<affiliation>
<address>
<email>alan@redhat.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2000</year>
<holder>Alan Cox</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The Z85x30 family synchronous/asynchronous controller chips are
used on a large number of cheap network interface cards. The
kernel provides a core interface layer that is designed to make
it easy to provide WAN services using this chip.
</para>
<para>
The current driver only support synchronous operation. Merging the
asynchronous driver support into this code to allow any Z85x30
device to be used as both a tty interface and as a synchronous
controller is a project for Linux post the 2.4 release
</para>
<para>
The support code handles most common card configurations and
supports running both Cisco HDLC and Synchronous PPP. With extra
glue the frame relay and X.25 protocols can also be used with this
driver.
</para>
</chapter>
<chapter>
<title>Driver Modes</title>
<para>
The Z85230 driver layer can drive Z8530, Z85C30 and Z85230 devices
in three different modes. Each mode can be applied to an individual
channel on the chip (each chip has two channels).
</para>
<para>
The PIO synchronous mode supports the most common Z8530 wiring. Here
the chip is interface to the I/O and interrupt facilities of the
host machine but not to the DMA subsystem. When running PIO the
Z8530 has extremely tight timing requirements. Doing high speeds,
even with a Z85230 will be tricky. Typically you should expect to
achieve at best 9600 baud with a Z8C530 and 64Kbits with a Z85230.
</para>
<para>
The DMA mode supports the chip when it is configured to use dual DMA
channels on an ISA bus. The better cards tend to support this mode
of operation for a single channel. With DMA running the Z85230 tops
out when it starts to hit ISA DMA constraints at about 512Kbits. It
is worth noting here that many PC machines hang or crash when the
chip is driven fast enough to hold the ISA bus solid.
</para>
<para>
Transmit DMA mode uses a single DMA channel. The DMA channel is used
for transmission as the transmit FIFO is smaller than the receive
FIFO. it gives better performance than pure PIO mode but is nowhere
near as ideal as pure DMA mode.
</para>
</chapter>
<chapter>
<title>Using the Z85230 driver</title>
<para>
The Z85230 driver provides the back end interface to your board. To
configure a Z8530 interface you need to detect the board and to
identify its ports and interrupt resources. It is also your problem
to verify the resources are available.
</para>
<para>
Having identified the chip you need to fill in a struct z8530_dev,
which describes each chip. This object must exist until you finally
shutdown the board. Firstly zero the active field. This ensures
nothing goes off without you intending it. The irq field should
be set to the interrupt number of the chip. (Each chip has a single
interrupt source rather than each channel). You are responsible
for allocating the interrupt line. The interrupt handler should be
set to <function>z8530_interrupt</function>. The device id should
be set to the z8530_dev structure pointer. Whether the interrupt can
be shared or not is board dependent, and up to you to initialise.
</para>
<para>
The structure holds two channel structures.
Initialise chanA.ctrlio and chanA.dataio with the address of the
control and data ports. You can or this with Z8530_PORT_SLEEP to
indicate your interface needs the 5uS delay for chip settling done
in software. The PORT_SLEEP option is architecture specific. Other
flags may become available on future platforms, eg for MMIO.
Initialise the chanA.irqs to &amp;z8530_nop to start the chip up
as disabled and discarding interrupt events. This ensures that
stray interrupts will be mopped up and not hang the bus. Set
chanA.dev to point to the device structure itself. The
private and name field you may use as you wish. The private field
is unused by the Z85230 layer. The name is used for error reporting
and it may thus make sense to make it match the network name.
</para>
<para>
Repeat the same operation with the B channel if your chip has
both channels wired to something useful. This isn't always the
case. If it is not wired then the I/O values do not matter, but
you must initialise chanB.dev.
</para>
<para>
If your board has DMA facilities then initialise the txdma and
rxdma fields for the relevant channels. You must also allocate the
ISA DMA channels and do any necessary board level initialisation
to configure them. The low level driver will do the Z8530 and
DMA controller programming but not board specific magic.
</para>
<para>
Having initialised the device you can then call
<function>z8530_init</function>. This will probe the chip and
reset it into a known state. An identification sequence is then
run to identify the chip type. If the checks fail to pass the
function returns a non zero error code. Typically this indicates
that the port given is not valid. After this call the
type field of the z8530_dev structure is initialised to either
Z8530, Z85C30 or Z85230 according to the chip found.
</para>
<para>
Once you have called z8530_init you can also make use of the utility
function <function>z8530_describe</function>. This provides a
consistent reporting format for the Z8530 devices, and allows all
the drivers to provide consistent reporting.
</para>
</chapter>
<chapter>
<title>Attaching Network Interfaces</title>
<para>
If you wish to use the network interface facilities of the driver,
then you need to attach a network device to each channel that is
present and in use. In addition to use the SyncPPP and Cisco HDLC
you need to follow some additional plumbing rules. They may seem
complex but a look at the example hostess_sv11 driver should
reassure you.
</para>
<para>
The network device used for each channel should be pointed to by
the netdevice field of each channel. The dev-&gt; priv field of the
network device points to your private data - you will need to be
able to find your ppp device from this. In addition to use the
sync ppp layer the private data must start with a void * pointer
to the syncppp structures.
</para>
<para>
The way most drivers approach this particular problem is to
create a structure holding the Z8530 device definition and
put that and the syncppp pointer into the private field of
the network device. The network device fields of the channels
then point back to the network devices. The ppp_device can also
be put in the private structure conveniently.
</para>
<para>
If you wish to use the synchronous ppp then you need to attach
the syncppp layer to the network device. You should do this before
you register the network device. The
<function>sppp_attach</function> requires that the first void *
pointer in your private data is pointing to an empty struct
ppp_device. The function fills in the initial data for the
ppp/hdlc layer.
</para>
<para>
Before you register your network device you will also need to
provide suitable handlers for most of the network device callbacks.
See the network device documentation for more details on this.
</para>
</chapter>
<chapter>
<title>Configuring And Activating The Port</title>
<para>
The Z85230 driver provides helper functions and tables to load the
port registers on the Z8530 chips. When programming the register
settings for a channel be aware that the documentation recommends
initialisation orders. Strange things happen when these are not
followed.
</para>
<para>
<function>z8530_channel_load</function> takes an array of
pairs of initialisation values in an array of u8 type. The first
value is the Z8530 register number. Add 16 to indicate the alternate
register bank on the later chips. The array is terminated by a 255.
</para>
<para>
The driver provides a pair of public tables. The
z8530_hdlc_kilostream table is for the UK 'Kilostream' service and
also happens to cover most other end host configurations. The
z8530_hdlc_kilostream_85230 table is the same configuration using
the enhancements of the 85230 chip. The configuration loaded is
standard NRZ encoded synchronous data with HDLC bitstuffing. All
of the timing is taken from the other end of the link.
</para>
<para>
When writing your own tables be aware that the driver internally
tracks register values. It may need to reload values. You should
therefore be sure to set registers 1-7, 9-11, 14 and 15 in all
configurations. Where the register settings depend on DMA selection
the driver will update the bits itself when you open or close.
Loading a new table with the interface open is not recommended.
</para>
<para>
There are three standard configurations supported by the core
code. In PIO mode the interface is programmed up to use
interrupt driven PIO. This places high demands on the host processor
to avoid latency. The driver is written to take account of latency
issues but it cannot avoid latencies caused by other drivers,
notably IDE in PIO mode. Because the drivers allocate buffers you
must also prevent MTU changes while the port is open.
</para>
<para>
Once the port is open it will call the rx_function of each channel
whenever a completed packet arrived. This is invoked from
interrupt context and passes you the channel and a network
buffer (struct sk_buff) holding the data. The data includes
the CRC bytes so most users will want to trim the last two
bytes before processing the data. This function is very timing
critical. When you wish to simply discard data the support
code provides the function <function>z8530_null_rx</function>
to discard the data.
</para>
<para>
To active PIO mode sending and receiving the <function>
z8530_sync_open</function> is called. This expects to be passed
the network device and the channel. Typically this is called from
your network device open callback. On a failure a non zero error
status is returned. The <function>z8530_sync_close</function>
function shuts down a PIO channel. This must be done before the
channel is opened again and before the driver shuts down
and unloads.
</para>
<para>
The ideal mode of operation is dual channel DMA mode. Here the
kernel driver will configure the board for DMA in both directions.
The driver also handles ISA DMA issues such as controller
programming and the memory range limit for you. This mode is
activated by calling the <function>z8530_sync_dma_open</function>
function. On failure a non zero error value is returned.
Once this mode is activated it can be shut down by calling the
<function>z8530_sync_dma_close</function>. You must call the close
function matching the open mode you used.
</para>
<para>
The final supported mode uses a single DMA channel to drive the
transmit side. As the Z85C30 has a larger FIFO on the receive
channel this tends to increase the maximum speed a little.
This is activated by calling the <function>z8530_sync_txdma_open
</function>. This returns a non zero error code on failure. The
<function>z8530_sync_txdma_close</function> function closes down
the Z8530 interface from this mode.
</para>
</chapter>
<chapter>
<title>Network Layer Functions</title>
<para>
The Z8530 layer provides functions to queue packets for
transmission. The driver internally buffers the frame currently
being transmitted and one further frame (in order to keep back
to back transmission running). Any further buffering is up to
the caller.
</para>
<para>
The function <function>z8530_queue_xmit</function> takes a network
buffer in sk_buff format and queues it for transmission. The
caller must provide the entire packet with the exception of the
bitstuffing and CRC. This is normally done by the caller via
the syncppp interface layer. It returns 0 if the buffer has been
queued and non zero values for queue full. If the function accepts
the buffer it becomes property of the Z8530 layer and the caller
should not free it.
</para>
<para>
The function <function>z8530_get_stats</function> returns a pointer
to an internally maintained per interface statistics block. This
provides most of the interface code needed to implement the network
layer get_stats callback.
</para>
</chapter>
<chapter>
<title>Porting The Z8530 Driver</title>
<para>
The Z8530 driver is written to be portable. In DMA mode it makes
assumptions about the use of ISA DMA. These are probably warranted
in most cases as the Z85230 in particular was designed to glue to PC
type machines. The PIO mode makes no real assumptions.
</para>
<para>
Should you need to retarget the Z8530 driver to another architecture
the only code that should need changing are the port I/O functions.
At the moment these assume PC I/O port accesses. This may not be
appropriate for all platforms. Replacing
<function>z8530_read_port</function> and <function>z8530_write_port
</function> is intended to be all that is required to port this
driver layer.
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
<variablelist>
<varlistentry><term>Interrupt Locking</term>
<listitem>
<para>
The locking in the driver is done via the global cli/sti lock. This
makes for relatively poor SMP performance. Switching this to use a
per device spin lock would probably materially improve performance.
</para>
</listitem></varlistentry>
<varlistentry><term>Occasional Failures</term>
<listitem>
<para>
We have reports of occasional failures when run for very long
periods of time and the driver starts to receive junk frames. At
the moment the cause of this is not clear.
</para>
</listitem></varlistentry>
</variablelist>
</para>
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Edrivers/net/wan/z85230.c
</chapter>
<chapter id="intfunctions">
<title>Internal Functions</title>
!Idrivers/net/wan/z85230.c
</chapter>
</book>