\documentclass[a4paper]{article}
\usepackage{epsfig}
\parindent=0pt
\parskip=4pt
\tolerance=9000
 
% use the entire page - I hope it doesn't get too long for US paper formats
\addtolength{\textwidth}{2\oddsidemargin}
\addtolength{\textheight}{2\topmargin}
\oddsidemargin=0pt
\evensidemargin=0pt
\topmargin=0pt

\begin{document}

\title{Linux ATM device driver interface \\
  Draft, version 0.0}

\author{Werner Almesberger \\
  EPFL, LRC \\
  {\tt werner.almesberger@lrc.di.epfl.ch}}
 
\date{November 3, 1995}

\maketitle
{
  \parskip=-1pt
  \setcounter{tocdepth}{2}
  \tableofcontents
}

\section{System overview}

Figure \ref{general} illustrates the environment a Linux ATM device driver
operates in. ``Device-independent ATM coordination'' is basically a set
of common data structures and conventions. ``Protocol'' denotes whatever
uses the ATM device driver in a given context. Currently, this is either
a raw transport or IP over ATM. ATM socket layer and protocol are
not clearly separated in the current implementation, so the distinction
between them may occasionally be somewhat arbitrary.

\begin{figure}[ht]
\begin{center}
\epsfig{file=general.eps,width=0.4\textwidth}
\end{center}
\caption{General ATM device access structure.}
\label{general}
\end{figure}

An ATM device driver consists of two parts: a usually small driver for
the physical layer unit (PHY) that controls physical layer operation and
gathers statistics, and the actual driver which is responsible for
controlling the segmentation and reassembly (SAR) process, resource
allocation, and for coordination with the protocol, the PHY driver, and
the hardware.
The reason for splitting the SAR and the PHY component is
mainly that one could expect that several different PHY chips are
used with the same SAR chip, and that the same PHY chip might actually
appear on several adapters using different SAR chips.

Normally, segmentation and reassembly and related functions are performed
directly in hardware, although a driver for very simplistic ATM adapters
may also perform those operations in software. Similarly, traffic shaping
is normally performed in hardware, but a driver may also do some or all
of it in software.

Only the SAR driver needs to have knowledge of how the hardware is
accessed. It provides an interface for accessing the PHY device to the PHY
driver.

Some of the device-independent data structures are also manipulated by the
socket layer. Note that some protocols (e.g. IP over ATM) may go through
additional layers before data eventually reaches a socket (if at all).

Figure \ref{pvc} gives a simplified view of the device-independent data
structures. Many of
the device-independent structures contain pointers to device-dependent
structures which are under the control of the device driver. 

\begin{figure}[htbp]
\begin{center}
\epsfig{file=devvcc.eps,width=\textwidth}
\end{center}
\caption{Device and VC data structures.}
\label{pvc}
\end{figure}

\verb"atm_dev" represents an ATM device. It contains pointers to device
operations (see section \ref{devops}), to operations on the PHY device
(see section \ref{phyops}), to the private data structures of the SAR and the
PHY drivers, the list of VC descriptors, and several sets of statistics
counters (one set per AAL).

A VC descriptor (\verb"atm_vcc") contains all information pertaining to a VC,
i.e. the VPI and VCI numbers, the AAL number, the address family, traffic
parameters, etc. In addition to that, there are a few pointers: back to the
device structure, to protocol functions (see section \ref{prtops}),
to driver-private data, to
protocol-private data, to the corresponding statistics block in the device
structure, to the receive queue, and to the next and the previous VC
descriptor.

The receive queue contains incoming SDUs waiting for final delivery by
the ATM socket layer. Queues for data waiting for transmission are
maintained by the device driver.


\section{Device data}

Device-independent ATM interface parameters are stored in
\verb"struct atm_dev":
\begin{verbatim}
%%include+ atmdev.h struct.atm_dev.{ ^}; s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"ops" points to the device operation function pointers, see also
section \ref{devops}. \verb"ops" is set by \verb"atm_dev_register" when
registering the device.

\verb"phy"
points to PHY device operation function pointers, see also section
\ref{phyops}. If there is no physical layer device or if it is directly
controlled by the SAR driver, \verb"phy" is not used and may be set to NULL.
Otherwise, the PHY driver initialization function has to set \verb"phy" when
invoked by the SAR driver.

\verb"type" points to the device type name. The device type is used to
identify the driver in kernel messages and typically indicates the
brand and the model number of the ATM adapter. \verb"number" is the
ATM interface number. \verb"type" and \verb"number" are set by
\verb"atm_dev_register".

\verb"vccs" points to the descriptor of the first VC of that device. If
there are no VCs, \verb"vccs" has to be set to NULL. It is initialized
to NULL by \verb"atm_dev_register". \verb"last" points to the last
VC descriptor or is undefined if there is none. VCs are placed in the
VC list in an arbitrary order.

\verb"dev_data" and \verb"phy_data" point to private data structures
belonging to the SAR driver and the PHY driver, respectively. The content
of these pointers is never accessed by any other part of the system than
by the respective driver. If a driver does not wish to use private data
structures, it can therefore leave the pointers uninitialized.

\verb"esi" contains the device's end system identifier (ESI). \verb"esi"
should be set during device initialization. If no ESI is available, the
array should be filled with zero bytes. \verb"prv" and \verb"pub" contain
the local ATM address of the interface. The same conventions as for the
corresponding fields in SVC address structures apply (see also
\cite{API}). \verb"prv" and \verb"pub" can be set or changed at any
time. They're initialized to zero by \verb"atm_dev_register".

\verb"ci_range" specifies the range of VPIs and VCIs that are supported
by that device. \verb"ci_range" has to be initialized during device
initialization and may be changed later by the device driver.

\verb"stats" contains counters for AAL-level events. The counters are
zero-initialized by \verb"atm_dev_register", maintained by the driver,
and read and possibly reset (zeroed) by device-independent functions.
Interrupts are disabled while reading or resetting the counters.

The counters are grouped in sets for each AAL type:
\begin{verbatim}
%%include+ atmdev.h struct.atm_dev_stats.{ ^}; s|\s*/\*.*||;s/^\n$//
\end{verbatim}

Each set has the following counters:
\begin{verbatim}
%%include+ atmdev.h struct.atm_aal_stats.{ ^}; s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"tx" and \verb"rx" count the PDUs that have successfully been sent
or received, respectively. \verb"tx_err" counts cases where an SDU
accepted for transmission was later discarded. \verb"rx_err" counts
PDUs received with a bad CRC, an invalid length, or a similar defect.
\verb"rx_drop" counts PDUs discarded because of memory shortage.\footnote{%
Note that {\tt rx\_err} and {\tt rx\_drop} may not only be incremented by the
device driver but also by the {\tt peek} function.} The behaviour on
overflows is undefined.


\section{VC data}
\label{vcdsc}

Device-independent VC parameters are stored in \verb"struct atm_vcc":
\begin{verbatim}
%%include+ atmdev.h struct.atm_vcc.{ ^}; s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"flags" contains flags indicating the VC state. The following
flags are relevant for the device driver:
\begin{description}
  \item[\tt ATM\_VF\_ADDR] indicates that the connection identifier stored in
    \verb"vpi" and \verb"vci" (see below) shall be considered to be
    ``in use''. This flag should be set by the device driver immediately
    before allocating the connection identifier in hardware, and the device
    driver must clear the flag immediately after freeing the connection
    identifier in hardware. Note that other entities may set \verb"ATM_VF_ADDR"
    before invoking the \verb"open" function.
  \item[\tt ATM\_VF\_READY] indicates that the VC is ready to transfer data.
    This flag must be set by the device driver when transfers are possible
    in all requested directions and it should be cleared by the device
    driver before closing the VC. Note that other entities may clear
    \verb"ATM_VF_READY" before requesting a close.
  \item[\tt ATM\_VF\_PARTIAL] indicates that resources are allocated to the
    (P)VC. This flag is entirely under the control of the device driver.
\end{description}

\verb"family" is the address family, i.e. either \verb"AF_ATMPVC" or
\verb"AF_ATMSVC". \verb"aal" contains the AAL number. \verb"dev" contains
a pointer to the corresponding device structure. \verb"txtp" and
\verb"rxtp" contain send and receive traffic parameters. All these fields
are initialized before the \verb"open" function is called.

\verb"tx_quota", \verb"rx_quota", \verb"tx_inuse", and \verb"rx_inuse"
describe the maximum size of the transmit and receive queues (in bytes)
and their current utilization. Those quotas are maintained and enforced
by the protocol.

\verb"vpi", and \verb"vci" contain the connection identifier. They have to
be set by the \verb"open" function.\footnote{The requested VPI and VCI are
passed to {\tt open} as arguments.}

\verb"aal_options" and \verb"atm_options" are reserved for future use.
The protocol operations \verb"push", \verb"pop", \verb"peek", and
\verb"push_oam" are described in section \ref{prtops}.

\verb"dev_data" points to device-specific private data, i.e. to a
device-specific VC descriptor. Similarly, \verb"proto_data" points to
protocol-specific data. Neither of those pointers is ever touched by
any other entity than the one owning it.

\verb"stats" points to the corresponding set of counters in the device
structure. The device driver shall use \verb"stats" to access statistics
counters (as opposed to accessing them via \verb"dev"). \verb"stats" is
initialized before \verb"open" is called.

\verb"timestamp", \verb"recvq", \verb"sleep", \verb"prev", \verb"next",
and all SVC-related fields should not be touched by the device driver.


\section{Socket buffer extensions}

The socket buffer structure \verb"struct sk_buff" (defined in \verb"skbuff.h")
is extended for ATM with the following fields:
\begin{verbatim}
%%include skbuff.h CONFIG_ATM endif s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"size", \verb"pos", and \verb"vcc" are reserved for internal use by
the device driver and not touched by any other entity.

\verb"iovcnt" contains the size of the scatter-gather vector. If no
scatter-gather is used, \verb"iovcnt" is set to zero. When using
scatter-gather, \verb"skb->data" points to an array of elements of
type \verb"struct iovec" and \verb"skb->len" indicates the total length
of all buffers. When receiving, \verb"iovcnt" must be initialized by
the device driver. When sending, \verb"iovcnt" is appropriately
initialized before \verb"send" is invoked.

\verb"timestamp" contains the time at which the cell was received.
\verb"timestamp" has to be set by the device driver
before calling the \verb"push" function.


\section{Device operations}
\label{devops}

Function pointers for ATM device operations are stored in
\verb"struct atmdev_ops":

\begin{verbatim}
%%include+ atmdev.h struct.atmdev_ops.{ ^}; s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"open" is invoked to open a VC in hardware. Many fields in the VC
descriptor are already initialized, see section \ref{vcdsc}. The VPI and
the VCI are passed as arguments. Note that they may be wildcarded or
incompletely specified. The device driver has to perform the requested
resource allocations and possibly select an appropriate VC. \verb"open"
returns zero if the operation has succeeded, or a negative error code if
the operation has failed. In case of a failure, \verb"open" must undo
all state changes (e.g. allocations) before returning.

\verb"close" is invoked to close a VC and to return all resources allocated
for it. \verb"close" is only invoked once per VC and only if the \verb"open"
operation was successful.

\verb"ioctl" passes a device ioctl to the device driver. Note that
\verb"arg" is passed ``as is'' from the calling process and may point to
memory locations that process is not allowed to access. If the SAR driver
does not recognize an ioctl, it must pass it on to the PHY driver if
one is defined and if it provides an \verb"ioctl" function.

\verb"getsockopt" and \verb"setsockopt" can be used to access driver-specific
variables. When calling \verb"getsockopt", \verb"optval" and \verb"optlen"
point to unchecked memory. When calling \verb"setsockopt", read access for
\verb"optval" has been checked. Unlike \verb"ioctl"s, unrecognized
\verb"getsockopt"s and
\verb"setsockopt"s are not forwarded to the PHY driver. Every ATM driver
should support \verb"SO_CIRANGE".

\verb"send" is used to enqueue SDUs for transmission. The socket buffer
(skb) must remain
accessible until the driver explicitly frees it by invoking the \verb"pop"
function. If no \verb"pop" function is provided, the driver must call
\verb"dev_kfree_skb(skb,FREE_WRITE)" instead. Of the ATM-specific skb
fields, only \verb"iovcnt" is initialized when \verb"send" is invoked.

\verb"sg_send" is used by the protocol to determine whether a packet
should be sent using scatter-gather. Drivers that don't implement
scatter-gather should set \verb"sg_send" to NULL. \verb"sg_send" examines
the start address and the length of the packet to estimate whether there
is a performance advantage in locking the packet in memory, building a
scatter-gather vector, and sending directly from user space (see also
\cite{LOWEND}), as opposed to copying the data to a kernel buffer and
sending that buffer. \verb"sg_send" returns zero if scatter-gather should
not be attempted, a non-zero value otherwise.

\verb"poll" is invoked before the protocol checks for the presence of
received data. Drivers which are not notified (e.g. by interrupts) when
new packets arrive need this function to poll their respective data source.
Interrupt-driven drivers should set \verb"poll" to NULL. The \verb"nonblock"
argument indicates whether the \verb"poll" function should wait until
something has been received (if zero) or not (if non-zero).
\verb"poll" may be removed at a
later time (a driver could also use timer-driven polling with similar
or better results).

\verb"send_oam" is used to send OAM cells. \verb"cell" points to the
cell in kernel memory. The same format as for AAL0 cells is used. \verb"flags"
indicates how the cell should be transmitted. The following flags are
defined:
\begin{description}
  \item[\tt ATM\_OF\_IMMED] immediate delivery requested (instead of
    in-sequence)
  \item[\tt ATM\_OF\_INRATE] in-rate delivery requested
\end{description}
If a driver is unable to support the requested transmission, it should not
fail the operation but use the closest available transmission method
(e.g. send immediately even if \verb"ATM_OF_IMMED" is not set) instead.
\verb"send_oam" may block for a short moment when performing in-sequence
or in-rate emission. Note that \verb"send_oam" may be invoked from an
interrupt and must therefore not try to sleep.
\verb"send_oam" is currently not used.

\verb"phy_put" is invoked by the PHY driver to write one byte to a register
of the PHY device. \verb"phy_get" is used to read a byte. Both functions
may be invoked from interrupts.  A SAR driver must provide those two functions
if it uses a PHY driver (and if the PHY device supports the corresponding
operation).

\verb"feedback" is invoked when the protocol or the socket has determined
at which memory address an incoming SDU will be stored. The start address
of the application-level SDU (i.e. after removing headers and trailers),
the destination address, and the size of the application-level SDU are
passed to \verb"feedback". This information can be used to adjust
parameters of heuristics used by the driver to predict optimal buffer
allocation for receiving. Note that the protocol is not obliged to ever
call \verb"feedback" upon delivery of a packet.

In addition to the functions in \verb"struct atmdev_ops", each SAR driver
must also provide a detect function which is invoked by
\verb"atmdev_init" (in \verb"atmdev_init.c").


\section{Protocol operations}
\label{prtops}

Protocol operations invoked by the device driver are defined in
\verb"struct atm_vcc":

\begin{verbatim}
%%include+ atmdev.h \*push \*push_oam s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"push" is invoked by the ATM driver to deliver received packets to
the protocol. Every protocol must provide a \verb"push" function. The
protocol acquires ownership of the skb and is responsible for freeing it
(with \verb"kfree_skb(skb,FREE_READ)").
\verb"push" is invoked by the socket layer with the \verb"skb" argument set
to NULL when the VC is closed, in order to detach the protocol from the VC.
Note that the device driver \verb"close" function is called before detaching
the protocol, so that the VC can no longer be used to send or receive data.

\verb"pop" is invoked after successful emission of a SDU to indicate that
the ATM driver will no longer use the skb. If no \verb"pop" function is
provided (i.e. if \verb"pop" is set to NULL), the driver calls
\verb"dev_kfree_skb(skb,FREE_WRITE)" instead.

\verb"peek" is invoked by a device driver whenever a new buffer has
to be allocated for an incoming packet. The size of the packet and,
optionally, a pointer to a function to examine the new packet are passed
to the protocol. The \verb"fetch" function can be used to read the
\verb"i"th 32 bits word from the packet, e.g. in order to improve buffer
alignment based on protocol or service information contained in a
packet header. Drivers which cannot provide such functionality must pass
NULL instead. \verb"peek" returns either an skb large enough for the
packet or it returns NULL, indicating that the packet should be
discarded. \verb"peek" has to update the statistics (\verb"vcc->stats")
in this case to indicate whether the packet was discarded due to lack
of memory (\verb"rx_drop") or due to some other problem (\verb"rx_err").

\verb"push_oam" is invoked whenever an OAM cell is received. A pointer to
the cell content is passed. The cell is stored in the same format as used
for AAL0. \verb"push_oam" can request in-sequence delivery of the cell
by returning a non-zero value. If \verb"push_oam" returns zero, the cell
is discarded afterwards. If \verb"push_oam" is set to NULL, all OAM cells
are delivered in-sequence. Hardware limitations may only allow approximative
in-sequence delivery.


\section{Physical layer operations}
\label{phyops}

Function pointers for physical layer device driver operations are stored in
\verb"struct atmphy_ops":

\begin{verbatim}
%%include+ atmdev.h struct.atmphy_ops.{ ^}; s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"start" is invoked by the SAR driver to start the PHY device.
This function is called at least once per interface.

\verb"ioctl" is invoked by the SAR driver to forward an ioctl that is
not understood by it. Each PHY driver for SONET should support the
\verb"SONET_GETSTATZ" and \verb"SONET_GETSTAT" ioctl. In addition to
that, the ioctls
\verb"SONET_SETDIAG", \verb"SONET_CLRDIAG", and \verb"SONET_GETDIAG"
should be supported if the hardware has the capability to simulate
errors. PHY drivers that don't support \verb"ioctl" should set the
fields to NULL.

\verb"interrupt" is invoked whenever the SAR driver receives an
interrupt which is triggered by the PHY device. This function is only
necessary if PHY interrupts are relayed through the SAR device and if
the PHY generates interrupts at all.

In addition to the functions in \verb"struct atmphy_ops", each SAR driver
must also provide an initialization function which is invoked by the
SAR driver. That function should initialize the PHY device and it has to
populate the \verb"dev->phy" field.


\section{Support functions}

Some device-independent support functions are defined in \verb"atmdev.h":

\begin{verbatim}
%%include+ atmdev.h atm_dev_register atm_find_ci s|\s*/\*.*||;s/^\n$//
\end{verbatim}

\verb"atm_dev_register" registers a new ATM device. Pointers to the interface
type name and to the device driver operations structure have to be passed.
Note that the type name must be accessible at the specified address until
after the device is
deregistered. \verb"atm_dev_register" either returns a pointer to a new,
initialized device structure, or NULL if no device structure was available
for allocation.

\verb"atm_dev_deregister" deregisters an ATM device. All activity on that
device must have been stopped before invoking \verb"atm_dev_deregister".
\verb"atm_dev_deregister" is typically used to deallocate device
structures after an initialization failures.

\verb"atm_find_ci" determines whether the specified connection identifier
is available on \verb"vcc->dev". If a wildcard is specified,
\verb"atm_find_ci" tries to locate an unused connection identifier. Note
that \verb"atm_find_ci" is comparably inefficient and that a device
driver may be able to perform noticeably faster lookups on its internal
tables. On success, \verb"atm_find_ci" sets \verb"vcc->vpi" and
\verb"vcc->vci" and returns zero. Otherwise, it returns a negative error
code.


\section{Summary}

Table \ref{fldown} summarizes ownership of fields contained in ATM-specific
data structures. Only fields relevant to ATM device drivers
are shown. Most of the fields are read by various system components, so
cross-references for read accesses would be only of marginal use.

\begin{table}[htbp]
\begin{center}
\begin{tabular}{|ll|ll|}
  \hline
  \bf Structure & \bf Field & \bf Initialized by & \bf Modified by \\
  \hline
  \tt atm\_dev & \tt ops & \tt atm\_dev\_register & --- \\
  \tt atm\_dev & \tt phy & PHY driver initialization (if applicable) & --- \\
  \tt atm\_dev & \tt type & \tt atm\_dev\_register & ---\\
  \tt atm\_dev & \tt dev\_data & SAR driver (if using field) & SAR driver \\
  \tt atm\_dev & \tt phy\_data & PHY driver (if using field) & PHY driver \\
  \tt atm\_dev & \tt esi & {\tt atm\_dev\_register}, SAR driver
			   initialization & SAR driver \\
  \tt atm\_dev & \tt ci\_range & SAR driver initialization & SAR driver \\
  \tt atm\_dev & \tt stats & \tt atm\_dev\_register\footnotemark &
    SAR driver, protocol \\
  \hline
  \tt atm\_vcc & \tt flags & ATM socket & Many components \\
  \tt atm\_vcc & \tt aal & ATM socket, protocol & --- \\
  \tt atm\_vcc & \tt dev & ATM socket & ATM socket\footnotemark \\
  \tt atm\_vcc & \tt txtp & ATM socket & SAR driver \\
  \tt atm\_vcc & \tt rxtp & ATM socket & SAR driver \\
  \tt atm\_vcc & \tt vpi & SAR driver & --- \\
  \tt atm\_vcc & \tt vci & SAR driver & --- \\
  \tt atm\_vcc & \tt aal\_options & ATM socket & ATM socket \\
  \tt atm\_vcc & \tt atm\_options & ATM socket & ATM socket \\
  \tt atm\_vcc & proto ops & Protocol & Protocol\footnotemark \\
  \tt atm\_vcc & \tt dev\_data & SAR driver & SAR driver \\
  \tt atm\_vcc & \tt proto\_data & Protocol & Protocol \\
  \tt atm\_vcc & \tt stats & ATM socket, protocol & --- \\
  \hline
  \tt sk\_buff & \tt atm.size & SAR driver (if using field) & SAR driver \\
  \tt sk\_buff & \tt atm.pos & SAR driver (if using field) & SAR driver \\
  \tt sk\_buff & \tt atm.vcc & SAR driver (if using field) & SAR driver \\
  \tt sk\_buff & \tt atm.iovcnt & TX: ATM socket, protocol & --- \\
  & &				  RX: SAR driver & --- \\
  \tt sk\_buff & \tt atm.timestamp & SAR driver & --- \\
  \hline
\end{tabular}
\end{center}
\caption{Summary of field ownership}
\label{fldown}
\end{table}
\addtocounter{footnote}{-2}
\footnotetext{Zeroed by device-independent functions.}
\addtocounter{footnote}{1}
\footnotetext{This modification occurs before the ATM device driver gets
  involved.}
\addtocounter{footnote}{1}
\footnotetext{E.g. IP over ATM redirects the {\tt push} function if the
  ATMARP demon requests to use a VC for IP traffic.}

Table \ref{allops} summarizes the operations that are provided by ATM
device drivers (SAR and PHY part) and by ATM protocol modules.
Again, only fields relevant to ATM device drivers
are shown. ``interrupt'' indicates that a function might be invoked during
an interrupt.

\begin{table}[htbp]
\begin{center}
\begin{tabular}{|ll|l|ll|}
  \hline
  \bf Structure & \bf Field & \bf Optional & \bf Provider & \bf Caller \\
  \hline
  \tt atmdev\_ops & \tt open & Yes & ATM driver & Protocol \\
  \tt atmdev\_ops & \tt close & Yes & ATM driver & Protocol \\
  \tt atmdev\_ops & \tt ioctl & Yes & ATM driver & ATM socket \\
  \tt atmdev\_ops & \tt getsockopt & Yes & ATM driver & ATM socket \\
  \tt atmdev\_ops & \tt setsockopt & Yes & ATM driver & ATM socket \\
  \tt atmdev\_ops & \tt send & No & ATM driver & Protocol \\
  \tt atmdev\_ops & \tt sg\_send & Yes & ATM driver & Protocol \\
  \tt atmdev\_ops & \tt poll & Yes & ATM driver & Any non-interrupt \\
  \tt atmdev\_ops & \tt send\_oam & Yes & ATM driver & Protocol, interrupt \\
  \tt atmdev\_ops & \tt phy\_put & No\footnotemark & SAR driver & PHY driver,
   interrupt \addtocounter{footnote}{-1} \\
  \tt atmdev\_ops & \tt phy\_get & No\footnotemark & SAR driver & PHY driver,
   interrupt \\
  \tt atmdev\_ops & \tt feedback & Yes & ATM driver & ATM socket \\
  \hline
  \tt atm\_vcc & \tt push & No & Protocol & ATM driver, interrupt \\
  \tt atm\_vcc & \tt pop & Yes & Protocol & ATM driver, interrupt \\
  \tt atm\_vcc & \tt peek & No & Protocol & ATM driver, interrupt \\
  \tt atm\_vcc & \tt push\_oam & No & Protocol & ATM driver, interrupt \\
  \hline
  --- & \tt fetch & Yes & ATM driver & Protocol, interrupt \\
  \hline
  --- & Detect & No & ATM driver & \tt atmdev\_init \\
  \hline
  \tt atmphy\_ops & \tt start & No & PHY driver & SAR driver \\
  \tt atmphy\_ops & \tt ioctl & Yes & PHY driver & SAR driver (called by
    socket) \\
  \tt atmphy\_ops & \tt interrupt & No\footnotemark & PHY driver &
    SAR driver, interrupt \\
  \hline
  --- & Initialization & No & PHY driver & SAR driver \\
  \hline
  --- & \tt atm\_dev\_register & No & Device-indep. & ATM driver \\
  --- & \tt atm\_dev\_deregister & No & Device-indep. & ATM driver \\
  --- & \tt atm\_find\_ci & No & Device-indep. & ATM driver \\
  \hline
\end{tabular}
\end{center}
\caption{Summary of protocol and driver operations}
\label{allops}
\end{table}
\addtocounter{footnote}{-1}
\footnotetext{A SAR driver may decide not to provide {\tt phy\_put} or
  {\tt get\_put} functions if all the PHY drivers it uses are known to test
  for unavailability of those functions.}
\addtocounter{footnote}{1}
\footnotetext{Only if interrupts are generated by the physical layer device
  and if they are relayed through the SAR driver.}


\begin{thebibliography}{API}
  \bibitem{LOWEND}Almesberger, Werner.
    {\em High-speed ATM networking on low-end computer systems},
    {\tt ftp://lrcftp.epfl.ch/pub/linux/atm/papers/atm\_on\_lowend.ps.gz},
    August 1995.
  \bibitem{API}Almesberger, Werner.
    {\em Linux ATM API},
    {\tt ftp://lrcftp.epfl.ch/pub/linux/atm/api/},
    October 1995.
\end{thebibliography}

\end{document}
