요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===============================
PARPORT interface documentation
===============================
:Time-stamp: <2000-02-24 13:30:20 twaugh>
Described here are the following functions:
Global functions::
parport_register_driver
parport_unregister_driver
parport_enumerate
parport_register_device
parport_unregister_device
parport_claim
parport_claim_or_block
parport_release
parport_yield
parport_yield_blocking
parport_wait_peripheral
parport_poll_peripheral
parport_wait_event
parport_negotiate
parport_read
parport_write
parport_open
parport_close
parport_device_id
parport_device_coords
parport_find_class
parport_find_device
parport_set_timeout
Port functions (can be overridden by low-level drivers):
SPP::
port->ops->read_data
port->ops->write_data
port->ops->read_status
port->ops->read_control
port->ops->write_control
port->ops->frob_control
port->ops->enable_irq
port->ops->disable_irq
port->ops->data_forward
port->ops->data_reverse
EPP::
port->ops->epp_write_data
port->ops->epp_read_data
port->ops->epp_write_addr
port->ops->epp_read_addr
ECP::
port->ops->ecp_write_data
port->ops->ecp_read_data
port->ops->ecp_write_addr
Other::
port->ops->nibble_read_data
port->ops->byte_read_data
port->ops->compat_write_data
The parport subsystem comprises ``parport`` (the core port-sharing
code), and a variety of low-level drivers that actually do the port
accesses. Each low-level driver handles a particular style of port
(PC, Amiga, and so on).
The parport interface to the device driver author can be broken down
into global functions and port functions.
The global functions are mostly for communicating between the device
driver and the parport subsystem: acquiring a list of available ports,
claiming a port for exclusive use, and so on. They also include
``generic`` functions for doing standard things that will work on any
IEEE 1284-capable architecture.
The port functions are provided by the low-level drivers, although the
core parport module provides generic ``defaults`` for some routines.
The port functions can be split into three groups: SPP, EPP, and ECP.
SPP (Standard Parallel Port) functions modify so-called ``SPP``
registers: data, status, and control. The hardware may not actually
have registers exactly like that, but the PC does and this interface is
modelled after common PC implementations. Other low-level drivers may
be able to emulate most of the functionality.
EPP (Enhanced Parallel Port) functions are provided for reading and
writing in IEEE 1284 EPP mode, and ECP (Extended Capabilities Port)
functions are used for IEEE 1284 ECP mode. (What about BECP? Does
anyone care?)
Hardware assistance for EPP and/or ECP transfers may or may not be
available, and if it is available it may or may not be used. If
hardware is not used, the transfer will be software-driven. In order
to cope with peripherals that only tenuously support IEEE 1284, a
low-level driver specific function is provided, for altering 'fudge
factors'.
Global functions
================
parport_register_driver - register a device driver with parport
---------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_driver {
const char *name;
void (*attach) (struct parport *);
void (*detach) (struct parport *);
struct parport_driver *next;
};
int parport_register_driver (struct parport_driver *driver);
DESCRIPTION
^^^^^^^^^^^
In order to be notified about parallel ports when they are detected,
parport_register_driver should be called. Your driver will
immediately be notified of all ports that have already been detected,
and of each new port as low-level drivers are loaded.
A ``struct parport_driver`` contains the textual name of your driver,
a pointer to a function to handle new ports, and a pointer to a
function to handle ports going away due to a low-level driver
unloading. Ports will only be detached if they are not being used
(i.e. there are no devices registered on them).
The visible parts of the ``struct parport *`` argument given to
attach/detach are::
struct parport
{
struct parport *next; /* next parport in list */
const char *name; /* port's name */
unsigned int modes; /* bitfield of hardware modes */
struct parport_device_info probe_info;
/* IEEE1284 info */
int number; /* parport index */
struct parport_operations *ops;
...
};
There are other members of the structure, but they should not be
touched.
The ``modes`` member summarises the capabilities of the underlying
hardware. It consists of flags which may be bitwise-ored together:
============================= ===============================================
PARPORT_MODE_PCSPP IBM PC registers are available,
i.e. functions that act on data,
control and status registers are
probably writing directly to the
hardware.
PARPORT_MODE_TRISTATE The data drivers may be turned off.
This allows the data lines to be used
for reverse (peripheral to host)
transfers.
PARPORT_MODE_COMPAT The hardware can assist with
compatibility-mode (printer)
transfers, i.e. compat_write_block.
PARPORT_MODE_EPP The hardware can assist with EPP
transfers.
PARPORT_MODE_ECP The hardware can assist with ECP
transfers.
PARPORT_MODE_DMA The hardware can use DMA, so you might
want to pass ISA DMA-able memory
(i.e. memory allocated using the
GFP_DMA flag with kmalloc) to the
low-level driver in order to take
advantage of it.
============================= ===============================================
There may be other flags in ``modes`` as well.
The contents of ``modes`` is advisory only. For example, if the
hardware is capable of DMA, and PARPORT_MODE_DMA is in ``modes``, it
doesn't necessarily mean that DMA will always be used when possible.
Similarly, hardware that is capable of assisting ECP transfers won't
necessarily be used.
RETURN VALUE
^^^^^^^^^^^^
Zero on success, otherwise an error code.
ERRORS
^^^^^^
None. (Can it fail? Why return int?)
EXAMPLE
^^^^^^^
::
static void lp_attach (struct parport *port)
{
...
private = kmalloc (...);
dev[count++] = parport_register_device (...);
...
}
static void lp_detach (struct parport *port)
{
...
}
static struct parport_driver lp_driver = {
"lp",
lp_attach,
lp_detach,
NULL /* always put NULL here */
};
int lp_init (void)
{
...
if (parport_register_driver (&lp_driver)) {
/* Failed; nothing we can do. */
return -EIO;
}
...
}
SEE ALSO
^^^^^^^^
parport_unregister_driver, parport_register_device, parport_enumerate
parport_unregister_driver - tell parport to forget about this driver
--------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_driver {
const char *name;
void (*attach) (struct parport *);
void (*detach) (struct parport *);
struct parport_driver *next;
};
void parport_unregister_driver (struct parport_driver *driver);
DESCRIPTION
^^^^^^^^^^^
This tells parport not to notify the device driver of new ports or of
ports going away. Registered devices belonging to that driver are NOT
unregistered: parport_unregister_device must be used for each one.
EXAMPLE
^^^^^^^
::
void cleanup_module (void)
{
...
/* Stop notifications. */
parport_unregister_driver (&lp_driver);
/* Unregister devices. */
for (i = 0; i < NUM_DEVS; i++)
parport_unregister_device (dev[i]);
...
}
SEE ALSO
^^^^^^^^
parport_register_driver, parport_enumerate
parport_enumerate - retrieve a list of parallel ports (DEPRECATED)
------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport *parport_enumerate (void);
DESCRIPTION
^^^^^^^^^^^
Retrieve the first of a list of valid parallel ports for this machine.
Successive parallel ports can be found using the ``struct parport
*next`` element of the ``struct parport *`` that is returned. If ``next``
is NULL, there are no more parallel ports in the list. The number of
ports in the list will not exceed PARPORT_MAX.
RETURN VALUE
^^^^^^^^^^^^
A ``struct parport *`` describing a valid parallel port for the machine,
or NULL if there are none.
ERRORS
^^^^^^
This function can return NULL to indicate that there are no parallel
ports to use.
EXAMPLE
^^^^^^^
::
int detect_device (void)
{
struct parport *port;
for (port = parport_enumerate ();
port != NULL;
port = port->next) {
/* Try to detect a device on the port... */
...
}
}
...
}
NOTES
^^^^^
parport_enumerate is deprecated; parport_register_driver should be
used instead.
SEE ALSO
^^^^^^^^
parport_register_driver, parport_unregister_driver
parport_register_device - register to use a port
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
typedef int (*preempt_func) (void *handle);
typedef void (*wakeup_func) (void *handle);
typedef int (*irq_func) (int irq, void *handle, struct pt_regs *);
struct pardevice *parport_register_device(struct parport *port,
const char *name,
preempt_func preempt,
wakeup_func wakeup,
irq_func irq,
int flags,
void *handle);
DESCRIPTION
^^^^^^^^^^^
Use this function to register your device driver on a parallel port
(``port``). Once you have done that, you will be able to use
parport_claim and parport_release in order to use the port.
The (``name``) argument is the name of the device that appears in /proc
filesystem. The string must be valid for the whole lifetime of the
device (until parport_unregister_device is called).
This function will register three callbacks into your driver:
``preempt``, ``wakeup`` and ``irq``. Each of these may be NULL in order to
indicate that you do not want a callback.
When the ``preempt`` function is called, it is because another driver
wishes to use the parallel port. The ``preempt`` function should return
non-zero if the parallel port cannot be released yet -- if zero is
returned, the port is lost to another driver and the port must be
re-claimed before use.
The ``wakeup`` function is called once another driver has released the
port and no other driver has yet claimed it. You can claim the
parallel port from within the ``wakeup`` function (in which case the
claim is guaranteed to succeed), or choose not to if you don't need it
now.
If an interrupt occurs on the parallel port your driver has claimed,
the ``irq`` function will be called. (Write something about shared
interrupts here.)
The ``handle`` is a pointer to driver-specific data, and is passed to
the callback functions.
``flags`` may be a bitwise combination of the following flags:
===================== =================================================
Flag Meaning
===================== =================================================
PARPORT_DEV_EXCL The device cannot share the parallel port at all.
Use this only when absolutely necessary.
===================== =================================================
The typedefs are not actually defined -- they are only shown in order
to make the function prototype more readable.
The visible parts of the returned ``struct pardevice`` are::
struct pardevice {
struct parport *port; /* Associated port */
void *private; /* Device driver's 'handle' */
...
};
RETURN VALUE
^^^^^^^^^^^^
A ``struct pardevice *``: a handle to the registered parallel port
device that can be used for parport_claim, parport_release, etc.
ERRORS
^^^^^^
A return value of NULL indicates that there was a problem registering
a device on that port.
EXAMPLE
^^^^^^^
::
static int preempt (void *handle)
{
if (busy_right_now)
return 1;
must_reclaim_port = 1;
return 0;
}
static void wakeup (void *handle)
{
struct toaster *private = handle;
struct pardevice *dev = private->dev;
if (!dev) return; /* avoid races */
if (want_port)
parport_claim (dev);
}
static int toaster_detect (struct toaster *private, struct parport *port)
{
private->dev = parport_register_device (port, "toaster", preempt,
wakeup, NULL, 0,
private);
if (!private->dev)
/* Couldn't register with parport. */
return -EIO;
must_reclaim_port = 0;
busy_right_now = 1;
parport_claim_or_block (private->dev);
...
/* Don't need the port while the toaster warms up. */
busy_right_now = 0;
...
busy_right_now = 1;
if (must_reclaim_port) {
parport_claim_or_block (private->dev);
must_reclaim_port = 0;
}
...
}
SEE ALSO
^^^^^^^^
parport_unregister_device, parport_claim
parport_unregister_device - finish using a port
-----------------------------------------------
SYNPOPSIS
::
#include <linux/parport.h>
void parport_unregister_device (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
This function is the opposite of parport_register_device. After using
parport_unregister_device, ``dev`` is no longer a valid device handle.
You should not unregister a device that is currently claimed, although
if you do it will be released automatically.
EXAMPLE
^^^^^^^
::
...
kfree (dev->private); /* before we lose the pointer */
parport_unregister_device (dev);
...
SEE ALSO
^^^^^^^^
parport_unregister_driver
parport_claim, parport_claim_or_block - claim the parallel port for a device
----------------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_claim (struct pardevice *dev);
int parport_claim_or_block (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
These functions attempt to gain control of the parallel port on which
``dev`` is registered. ``parport_claim`` does not block, but
``parport_claim_or_block`` may do. (Put something here about blocking
interruptibly or non-interruptibly.)
You should not try to claim a port that you have already claimed.
RETURN VALUE
^^^^^^^^^^^^
A return value of zero indicates that the port was successfully
claimed, and the caller now has possession of the parallel port.
If ``parport_claim_or_block`` blocks before returning successfully, the
return value is positive.
ERRORS
^^^^^^
========== ==========================================================
-EAGAIN The port is unavailable at the moment, but another attempt
to claim it may succeed.
========== ==========================================================
SEE ALSO
^^^^^^^^
parport_release
parport_release - release the parallel port
-------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
void parport_release (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
Once a parallel port device has been claimed, it can be released using
``parport_release``. It cannot fail, but you should not release a
device that you do not have possession of.
EXAMPLE
^^^^^^^
::
static size_t write (struct pardevice *dev, const void *buf,
size_t len)
{
...
written = dev->port->ops->write_ecp_data (dev->port, buf,
len);
parport_release (dev);
...
}
SEE ALSO
^^^^^^^^
change_mode, parport_claim, parport_claim_or_block, parport_yield
parport_yield, parport_yield_blocking - temporarily release a parallel port
---------------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_yield (struct pardevice *dev)
int parport_yield_blocking (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
When a driver has control of a parallel port, it may allow another
driver to temporarily ``borrow`` it. ``parport_yield`` does not block;
``parport_yield_blocking`` may do.
RETURN VALUE
^^^^^^^^^^^^
A return value of zero indicates that the caller still owns the port
and the call did not block.
A positive return value from ``parport_yield_blocking`` indicates that
the caller still owns the port and the call blocked.
A return value of -EAGAIN indicates that the caller no longer owns the
port, and it must be re-claimed before use.
ERRORS
^^^^^^
========= ==========================================================
-EAGAIN Ownership of the parallel port was given away.
========= ==========================================================
SEE ALSO
^^^^^^^^
parport_release
parport_wait_peripheral - wait for status lines, up to 35ms
-----------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_wait_peripheral (struct parport *port,
unsigned char mask,
unsigned char val);
DESCRIPTION
^^^^^^^^^^^
Wait for the status lines in mask to match the values in val.
RETURN VALUE
^^^^^^^^^^^^
======== ==========================================================
-EINTR a signal is pending
0 the status lines in mask have values in val
1 timed out while waiting (35ms elapsed)
======== ==========================================================
SEE ALSO
^^^^^^^^
parport_poll_peripheral
parport_poll_peripheral - wait for status lines, in usec
--------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_poll_peripheral (struct parport *port,
unsigned char mask,
unsigned char val,
int usec);
DESCRIPTION
^^^^^^^^^^^
Wait for the status lines in mask to match the values in val.
RETURN VALUE
^^^^^^^^^^^^
======== ==========================================================
-EINTR a signal is pending
0 the status lines in mask have values in val
1 timed out while waiting (usec microseconds have elapsed)
======== ==========================================================
SEE ALSO
^^^^^^^^
parport_wait_peripheral
parport_wait_event - wait for an event on a port
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_wait_event (struct parport *port, signed long timeout)
DESCRIPTION
^^^^^^^^^^^
Wait for an event (e.g. interrupt) on a port. The timeout is in
jiffies.
RETURN VALUE
^^^^^^^^^^^^
======= ==========================================================
0 success
<0 error (exit as soon as possible)
>0 timed out
======= ==========================================================
parport_negotiate - perform IEEE 1284 negotiation
-------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_negotiate (struct parport *, int mode);
DESCRIPTION
^^^^^^^^^^^
Perform IEEE 1284 negotiation.
RETURN VALUE
^^^^^^^^^^^^
======= ==========================================================
0 handshake OK; IEEE 1284 peripheral and mode available
-1 handshake failed; peripheral not compliant (or none present)
1 handshake OK; IEEE 1284 peripheral present but mode not
available
======= ==========================================================
SEE ALSO
^^^^^^^^
parport_read, parport_write
parport_read - read data from device
------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
ssize_t parport_read (struct parport *, void *buf, size_t len);
DESCRIPTION
^^^^^^^^^^^
Read data from device in current IEEE 1284 transfer mode. This only
works for modes that support reverse data transfer.
RETURN VALUE
^^^^^^^^^^^^
If negative, an error code; otherwise the number of bytes transferred.
SEE ALSO
^^^^^^^^
parport_write, parport_negotiate
parport_write - write data to device
------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
ssize_t parport_write (struct parport *, const void *buf, size_t len);
DESCRIPTION
^^^^^^^^^^^
Write data to device in current IEEE 1284 transfer mode. This only
works for modes that support forward data transfer.
RETURN VALUE
^^^^^^^^^^^^
If negative, an error code; otherwise the number of bytes transferred.
SEE ALSO
^^^^^^^^
parport_read, parport_negotiate
parport_open - register device for particular device number
-----------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct pardevice *parport_open (int devnum, const char *name,
int (*pf) (void *),
void (*kf) (void *),
void (*irqf) (int, void *,
struct pt_regs *),
int flags, void *handle);
DESCRIPTION
^^^^^^^^^^^
This is like parport_register_device but takes a device number instead
of a pointer to a struct parport.
RETURN VALUE
^^^^^^^^^^^^
See parport_register_device. If no device is associated with devnum,
NULL is returned.
SEE ALSO
^^^^^^^^
parport_register_device
parport_close - unregister device for particular device number
--------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
void parport_close (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
This is the equivalent of parport_unregister_device for parport_open.
SEE ALSO
^^^^^^^^
parport_unregister_device, parport_open
parport_device_id - obtain IEEE 1284 Device ID
----------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
ssize_t parport_device_id (int devnum, char *buffer, size_t len);
DESCRIPTION
^^^^^^^^^^^
Obtains the IEEE 1284 Device ID associated with a given device.
RETURN VALUE
^^^^^^^^^^^^
If negative, an error code; otherwise, the number of bytes of buffer
that contain the device ID. The format of the device ID is as
follows::
[length][ID]
The first two bytes indicate the inclusive length of the entire Device
ID, and are in big-endian order. The ID is a sequence of pairs of the
form::
key:value;
NOTES
^^^^^
Many devices have ill-formed IEEE 1284 Device IDs.
SEE ALSO
^^^^^^^^
parport_find_class, parport_find_device
parport_device_coords - convert device number to device coordinates
-------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_device_coords (int devnum, int *parport, int *mux,
int *daisy);
DESCRIPTION
^^^^^^^^^^^
Convert between device number (zero-based) and device coordinates
(port, multiplexor, daisy chain address).
RETURN VALUE
^^^^^^^^^^^^
Zero on success, in which case the coordinates are (``*parport``, ``*mux``,
``*daisy``).
SEE ALSO
^^^^^^^^
parport_open, parport_device_id
parport_find_class - find a device by its class
-----------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
typedef enum {
PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */
PARPORT_CLASS_PRINTER,
PARPORT_CLASS_MODEM,
PARPORT_CLASS_NET,
PARPORT_CLASS_HDC, /* Hard disk controller */
PARPORT_CLASS_PCMCIA,
PARPORT_CLASS_MEDIA, /* Multimedia device */
PARPORT_CLASS_FDC, /* Floppy disk controller */
PARPORT_CLASS_PORTS,
PARPORT_CLASS_SCANNER,
PARPORT_CLASS_DIGCAM,
PARPORT_CLASS_OTHER, /* Anything else */
PARPORT_CLASS_UNSPEC, /* No CLS field in ID */
PARPORT_CLASS_SCSIADAPTER
} parport_device_class;
int parport_find_class (parport_device_class cls, int from);
DESCRIPTION
^^^^^^^^^^^
Find a device by class. The search starts from device number from+1.
RETURN VALUE
^^^^^^^^^^^^
The device number of the next device in that class, or -1 if no such
device exists.
NOTES
^^^^^
Example usage::
int devnum = -1;
while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, devnum)) != -1) {
struct pardevice *dev = parport_open (devnum, ...);
...
}
SEE ALSO
^^^^^^^^
parport_find_device, parport_open, parport_device_id
parport_find_device - find a device by its class
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_find_device (const char *mfg, const char *mdl, int from);
DESCRIPTION
^^^^^^^^^^^
Find a device by vendor and model. The search starts from device
number from+1.
RETURN VALUE
^^^^^^^^^^^^
The device number of the next device matching the specifications, or
-1 if no such device exists.
NOTES
^^^^^
Example usage::
int devnum = -1;
while ((devnum = parport_find_device ("IOMEGA", "ZIP+", devnum)) != -1) {
struct pardevice *dev = parport_open (devnum, ...);
...
}
SEE ALSO
^^^^^^^^
parport_find_class, parport_open, parport_device_id
parport_set_timeout - set the inactivity timeout
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
long parport_set_timeout (struct pardevice *dev, long inactivity);
DESCRIPTION
^^^^^^^^^^^
Set the inactivity timeout, in jiffies, for a registered device. The
previous timeout is returned.
RETURN VALUE
^^^^^^^^^^^^
The previous timeout, in jiffies.
NOTES
^^^^^
Some of the port->ops functions for a parport may take time, owing to
delays at the peripheral. After the peripheral has not responded for
``inactivity`` jiffies, a timeout will occur and the blocking function
will return.
A timeout of 0 jiffies is a special case: the function must do as much
as it can without blocking or leaving the hardware in an unknown
state. If port operations are performed from within an interrupt
handler, for instance, a timeout of 0 jiffies should be used.
Once set for a registered device, the timeout will remain at the set
value until set again.
SEE ALSO
^^^^^^^^
port->ops->xxx_read/write_yyy
PORT FUNCTIONS
==============
The functions in the port->ops structure (struct parport_operations)
are provided by the low-level driver responsible for that port.
port->ops->read_data - read the data register
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*read_data) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
If port->modes contains the PARPORT_MODE_TRISTATE flag and the
PARPORT_CONTROL_DIRECTION bit in the control register is set, this
returns the value on the data pins. If port->modes contains the
PARPORT_MODE_TRISTATE flag and the PARPORT_CONTROL_DIRECTION bit is
not set, the return value _may_ be the last value written to the data
register. Otherwise the return value is undefined.
SEE ALSO
^^^^^^^^
write_data, read_status, write_control
port->ops->write_data - write the data register
-----------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*write_data) (struct parport *port, unsigned char d);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes to the data register. May have side-effects (a STROBE pulse,
for instance).
SEE ALSO
^^^^^^^^
read_data, read_status, write_control
port->ops->read_status - read the status register
-------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*read_status) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads from the status register. This is a bitmask:
- PARPORT_STATUS_ERROR (printer fault, "nFault")
- PARPORT_STATUS_SELECT (on-line, "Select")
- PARPORT_STATUS_PAPEROUT (no paper, "PError")
- PARPORT_STATUS_ACK (handshake, "nAck")
- PARPORT_STATUS_BUSY (busy, "Busy")
There may be other bits set.
SEE ALSO
^^^^^^^^
read_data, write_data, write_control
port->ops->read_control - read the control register
---------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*read_control) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Returns the last value written to the control register (either from
write_control or frob_control). No port access is performed.
SEE ALSO
^^^^^^^^
read_data, write_data, read_status, write_control
port->ops->write_control - write the control register
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*write_control) (struct parport *port, unsigned char s);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes to the control register. This is a bitmask::
_______
- PARPORT_CONTROL_STROBE (nStrobe)
_______
- PARPORT_CONTROL_AUTOFD (nAutoFd)
_____
- PARPORT_CONTROL_INIT (nInit)
_________
- PARPORT_CONTROL_SELECT (nSelectIn)
SEE ALSO
^^^^^^^^
read_data, write_data, read_status, frob_control
port->ops->frob_control - write control register bits
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*frob_control) (struct parport *port,
unsigned char mask,
unsigned char val);
...
};
DESCRIPTION
^^^^^^^^^^^
This is equivalent to reading from the control register, masking out
the bits in mask, exclusive-or'ing with the bits in val, and writing
the result to the control register.
As some ports don't allow reads from the control port, a software copy
of its contents is maintained, so frob_control is in fact only one
port access.
SEE ALSO
^^^^^^^^
read_data, write_data, read_status, write_control
port->ops->enable_irq - enable interrupt generation
---------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*enable_irq) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
The parallel port hardware is instructed to generate interrupts at
appropriate moments, although those moments are
architecture-specific. For the PC architecture, interrupts are
commonly generated on the rising edge of nAck.
SEE ALSO
^^^^^^^^
disable_irq
port->ops->disable_irq - disable interrupt generation
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*disable_irq) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
The parallel port hardware is instructed not to generate interrupts.
The interrupt itself is not masked.
SEE ALSO
^^^^^^^^
enable_irq
port->ops->data_forward - enable data drivers
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*data_forward) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Enables the data line drivers, for 8-bit host-to-peripheral
communications.
SEE ALSO
^^^^^^^^
data_reverse
port->ops->data_reverse - tristate the buffer
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*data_reverse) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Places the data bus in a high impedance state, if port->modes has the
PARPORT_MODE_TRISTATE bit set.
SEE ALSO
^^^^^^^^
data_forward
port->ops->epp_write_data - write EPP data
------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_write_data) (struct parport *port, const void *buf,
size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes data in EPP mode, and returns the number of bytes written.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
SEE ALSO
^^^^^^^^
epp_read_data, epp_write_addr, epp_read_addr
port->ops->epp_read_data - read EPP data
----------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_read_data) (struct parport *port, void *buf,
size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads data in EPP mode, and returns the number of bytes read.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
SEE ALSO
^^^^^^^^
epp_write_data, epp_write_addr, epp_read_addr
port->ops->epp_write_addr - write EPP address
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_write_addr) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes EPP addresses (8 bits each), and returns the number written.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
(Does PARPORT_EPP_FAST make sense for this function?)
SEE ALSO
^^^^^^^^
epp_write_data, epp_read_data, epp_read_addr
port->ops->epp_read_addr - read EPP address
-------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_read_addr) (struct parport *port, void *buf,
size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads EPP addresses (8 bits each), and returns the number read.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
(Does PARPORT_EPP_FAST make sense for this function?)
SEE ALSO
^^^^^^^^
epp_write_data, epp_read_data, epp_write_addr
port->ops->ecp_write_data - write a block of ECP data
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*ecp_write_data) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes a block of ECP data. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes written.
SEE ALSO
^^^^^^^^
ecp_read_data, ecp_write_addr
port->ops->ecp_read_data - read a block of ECP data
---------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*ecp_read_data) (struct parport *port,
void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads a block of ECP data. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes read. NB. There may be more unread data in a
FIFO. Is there a way of stunning the FIFO to prevent this?
SEE ALSO
^^^^^^^^
ecp_write_block, ecp_write_addr
port->ops->ecp_write_addr - write a block of ECP addresses
----------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*ecp_write_addr) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes a block of ECP addresses. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes written.
NOTES
^^^^^
This may use a FIFO, and if so shall not return until the FIFO is empty.
SEE ALSO
^^^^^^^^
ecp_read_data, ecp_write_data
port->ops->nibble_read_data - read a block of data in nibble mode
-----------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*nibble_read_data) (struct parport *port,
void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads a block of data in nibble mode. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of whole bytes read.
SEE ALSO
^^^^^^^^
byte_read_data, compat_write_data
port->ops->byte_read_data - read a block of data in byte mode
-------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*byte_read_data) (struct parport *port,
void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads a block of data in byte mode. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes read.
SEE ALSO
^^^^^^^^
nibble_read_data, compat_write_data
port->ops->compat_write_data - write a block of data in compatibility mode
--------------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*compat_write_data) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes a block of data in compatibility mode. The ``flags`` parameter
is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes written.
SEE ALSO
^^^^^^^^
nibble_read_data, byte_read_data
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
병렬 포트 저수준 드라이버 API의 구성
1-99이 문서는 Linux 병렬 포트 공유 계층인 `parport`가 제공하는 저수준 API를 설명합니다. 병렬 포트를 사용하는 장치 드라이버는 전역 함수로 포트와 장치를 등록하고 소유권을 조정하며, 실제 레지스터 접근과 IEEE 1284 전송은 포트별 저수준 드라이버가 채운 `struct parport_operations`, 즉 `port->ops`를 통해 수행합니다.
전역 함수에는 드라이버·장치 등록과 해제, 포트 claim·release·yield, 상태선 대기, IEEE 1284 협상과 읽기·쓰기, 장치 번호 탐색, inactivity timeout 설정이 포함됩니다. 포트 함수에는 SPP 레지스터 접근, IRQ 제어, 데이터 버스 방향 전환, EPP·ECP·nibble·byte·compatibility 전송이 포함됩니다.
`parport` 코어는 여러 장치 드라이버가 한 병렬 포트를 공유하도록 중재합니다. 저수준 포트 드라이버는 가능한 경우 하드웨어 EPP/ECP 기능을 제공하고, 그렇지 않으면 SPP 레지스터 연산을 조합해 소프트웨어 방식으로 해당 전송을 에뮬레이션할 수 있습니다.
이후 절의 함수 이름, C 형식, 상수, 구조체 필드와 source path는 원문 표기를 유지합니다. 호출자는 먼저 포트와 장치의 수명 및 소유권을 확보한 뒤, 지원 모드와 timeout 조건에 맞는 전송 연산을 선택해야 합니다.
장치 드라이버 요청이 공유 계층의 중재를 거쳐 포트별 하드웨어 연산으로 내려갑니다.
===============================
PARPORT interface documentation
===============================
:Time-stamp: <2000-02-24 13:30:20 twaugh>
Described here are the following functions:
Global functions::
parport_register_driver
parport_unregister_driver
parport_enumerate
parport_register_device
parport_unregister_device
parport_claim
parport_claim_or_block
parport_release
parport_yield
parport_yield_blocking
parport_wait_peripheral
parport_poll_peripheral
parport_wait_event
parport_negotiate
parport_read
parport_write
parport_open
parport_close
parport_device_id
parport_device_coords
parport_find_class
parport_find_device
parport_set_timeout
Port functions (can be overridden by low-level drivers):
SPP::
port->ops->read_data
port->ops->write_data
port->ops->read_status
port->ops->read_control
port->ops->write_control
port->ops->frob_control
port->ops->enable_irq
port->ops->disable_irq
port->ops->data_forward
port->ops->data_reverse
EPP::
port->ops->epp_write_data
port->ops->epp_read_data
port->ops->epp_write_addr
port->ops->epp_read_addr
ECP::
port->ops->ecp_write_data
port->ops->ecp_read_data
port->ops->ecp_write_addr
Other::
port->ops->nibble_read_data
port->ops->byte_read_data
port->ops->compat_write_data
The parport subsystem comprises ``parport`` (the core port-sharing
code), and a variety of low-level drivers that actually do the port
accesses. Each low-level driver handles a particular style of port
(PC, Amiga, and so on).
The parport interface to the device driver author can be broken down
into global functions and port functions.
The global functions are mostly for communicating between the device
driver and the parport subsystem: acquiring a list of available ports,
claiming a port for exclusive use, and so on. They also include
``generic`` functions for doing standard things that will work on any
IEEE 1284-capable architecture.
The port functions are provided by the low-level drivers, although the
core parport module provides generic ``defaults`` for some routines.
The port functions can be split into three groups: SPP, EPP, and ECP.
SPP (Standard Parallel Port) functions modify so-called ``SPP``
registers: data, status, and control. The hardware may not actually
have registers exactly like that, but the PC does and this interface is
modelled after common PC implementations. Other low-level drivers may
be able to emulate most of the functionality.
EPP (Enhanced Parallel Port) functions are provided for reading and
writing in IEEE 1284 EPP mode, and ECP (Extended Capabilities Port)
functions are used for IEEE 1284 ECP mode. (What about BECP? Does
anyone care?)
Hardware assistance for EPP and/or ECP transfers may or may not be
available, and if it is available it may or may not be used. If
hardware is not used, the transfer will be software-driven. In order
to cope with peripherals that only tenuously support IEEE 1284, a
low-level driver specific function is provided, for altering 'fudge
factors'.
`parport_register_driver()`와 포트 발견
100-241`parport_register_driver()`는 병렬 포트 장치 드라이버를 parport 코어에 등록합니다. 등록이 끝나면 이미 존재하는 모든 포트에 대해 드라이버의 `attach` 콜백이 즉시 호출되고, 이후 새 포트가 등록될 때도 같은 알림을 받습니다. 포트를 담당하던 저수준 드라이버가 제거될 때에는 해당 포트에 등록된 장치가 없는 경우 `detach` 콜백이 호출됩니다.
드라이버가 볼 수 있는 `struct parport`의 주요 필드는 연결 리스트의 `next`, 포트 `name`, 지원 능력을 나타내는 `modes`, probe 정보 배열 `probe_info`, 포트 `number`, 하위 연산 집합 `ops`입니다. `modes`는 `PARPORT_MODE_PCSPP`, `PARPORT_MODE_TRISTATE`, `PARPORT_MODE_COMPAT`, `PARPORT_MODE_EPP`, `PARPORT_MODE_ECP`, `PARPORT_MODE_DMA`의 비트 조합입니다.
모드 플래그는 조언 정보일 뿐입니다. 예를 들어 `PARPORT_MODE_ECP`가 없더라도 드라이버가 `port->ops->ecp_write_data()`를 호출하면 parport 코어가 소프트웨어 ECP 전송을 시도할 수 있습니다. 따라서 하드웨어 가속 가능 여부와 API 사용 가능 여부를 동일하게 취급해서는 안 됩니다.
등록이 성공하면 0을 반환하고, 실패하면 음수 오류 코드를 반환합니다. 원문은 현재 예상되는 오류가 없다고 덧붙입니다. 예제의 `lp` 드라이버는 `attach`와 `detach`를 제공하는 `parport_driver`를 정적으로 만들고 `module_init()`에서 등록합니다.
Global functions
================
parport_register_driver - register a device driver with parport
---------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_driver {
const char *name;
void (*attach) (struct parport *);
void (*detach) (struct parport *);
struct parport_driver *next;
};
int parport_register_driver (struct parport_driver *driver);
DESCRIPTION
^^^^^^^^^^^
In order to be notified about parallel ports when they are detected,
parport_register_driver should be called. Your driver will
immediately be notified of all ports that have already been detected,
and of each new port as low-level drivers are loaded.
A ``struct parport_driver`` contains the textual name of your driver,
a pointer to a function to handle new ports, and a pointer to a
function to handle ports going away due to a low-level driver
unloading. Ports will only be detached if they are not being used
(i.e. there are no devices registered on them).
The visible parts of the ``struct parport *`` argument given to
attach/detach are::
struct parport
{
struct parport *next; /* next parport in list */
const char *name; /* port's name */
unsigned int modes; /* bitfield of hardware modes */
struct parport_device_info probe_info;
/* IEEE1284 info */
int number; /* parport index */
struct parport_operations *ops;
...
};
There are other members of the structure, but they should not be
touched.
The ``modes`` member summarises the capabilities of the underlying
hardware. It consists of flags which may be bitwise-ored together:
============================= ===============================================
PARPORT_MODE_PCSPP IBM PC registers are available,
i.e. functions that act on data,
control and status registers are
probably writing directly to the
hardware.
PARPORT_MODE_TRISTATE The data drivers may be turned off.
This allows the data lines to be used
for reverse (peripheral to host)
transfers.
PARPORT_MODE_COMPAT The hardware can assist with
compatibility-mode (printer)
transfers, i.e. compat_write_block.
PARPORT_MODE_EPP The hardware can assist with EPP
transfers.
PARPORT_MODE_ECP The hardware can assist with ECP
transfers.
PARPORT_MODE_DMA The hardware can use DMA, so you might
want to pass ISA DMA-able memory
(i.e. memory allocated using the
GFP_DMA flag with kmalloc) to the
low-level driver in order to take
advantage of it.
============================= ===============================================
There may be other flags in ``modes`` as well.
The contents of ``modes`` is advisory only. For example, if the
hardware is capable of DMA, and PARPORT_MODE_DMA is in ``modes``, it
doesn't necessarily mean that DMA will always be used when possible.
Similarly, hardware that is capable of assisting ECP transfers won't
necessarily be used.
RETURN VALUE
^^^^^^^^^^^^
Zero on success, otherwise an error code.
ERRORS
^^^^^^
None. (Can it fail? Why return int?)
EXAMPLE
^^^^^^^
::
static void lp_attach (struct parport *port)
{
...
private = kmalloc (...);
dev[count++] = parport_register_device (...);
...
}
static void lp_detach (struct parport *port)
{
...
}
static struct parport_driver lp_driver = {
"lp",
lp_attach,
lp_detach,
NULL /* always put NULL here */
};
int lp_init (void)
{
...
if (parport_register_driver (&lp_driver)) {
/* Failed; nothing we can do. */
return -EIO;
}
...
}
SEE ALSO
^^^^^^^^
parport_unregister_driver, parport_register_device, parport_enumerate
`parport_unregister_driver()`와 폐기된 열거 방식
242-356`parport_unregister_driver()`는 앞서 `parport_register_driver()`로 등록한 드라이버를 parport 코어에서 제거합니다. 이 호출 이후에는 포트가 추가되거나 제거되어도 `attach`·`detach` 알림을 더 이상 받지 않습니다.
이 함수는 드라이버가 등록해 둔 `struct pardevice`를 대신 해제하지 않습니다. 각 장치 등록은 드라이버가 직접 추적하여 `parport_unregister_device()`로 정리해야 하며, 드라이버 등록 해제와 장치 수명 종료를 같은 작업으로 간주하면 안 됩니다.
`parport_enumerate()`는 등록된 병렬 포트 연결 리스트의 첫 항목을 반환하는 오래된 인터페이스입니다. 리스트는 `PARPORT_MAX`개까지 이어지며 마지막 항목의 `next`는 `NULL`입니다. 포트가 없으면 함수 자체가 `NULL`을 반환합니다.
직접 열거는 폐기됐습니다. 포트가 나중에 추가·제거되는 동적 환경을 빠뜨리지 않도록 새 코드는 `parport_register_driver()`와 `attach`·`detach` 콜백을 사용해야 합니다.
parport_unregister_driver - tell parport to forget about this driver
--------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_driver {
const char *name;
void (*attach) (struct parport *);
void (*detach) (struct parport *);
struct parport_driver *next;
};
void parport_unregister_driver (struct parport_driver *driver);
DESCRIPTION
^^^^^^^^^^^
This tells parport not to notify the device driver of new ports or of
ports going away. Registered devices belonging to that driver are NOT
unregistered: parport_unregister_device must be used for each one.
EXAMPLE
^^^^^^^
::
void cleanup_module (void)
{
...
/* Stop notifications. */
parport_unregister_driver (&lp_driver);
/* Unregister devices. */
for (i = 0; i < NUM_DEVS; i++)
parport_unregister_device (dev[i]);
...
}
SEE ALSO
^^^^^^^^
parport_register_driver, parport_enumerate
parport_enumerate - retrieve a list of parallel ports (DEPRECATED)
------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport *parport_enumerate (void);
DESCRIPTION
^^^^^^^^^^^
Retrieve the first of a list of valid parallel ports for this machine.
Successive parallel ports can be found using the ``struct parport
*next`` element of the ``struct parport *`` that is returned. If ``next``
is NULL, there are no more parallel ports in the list. The number of
ports in the list will not exceed PARPORT_MAX.
RETURN VALUE
^^^^^^^^^^^^
A ``struct parport *`` describing a valid parallel port for the machine,
or NULL if there are none.
ERRORS
^^^^^^
This function can return NULL to indicate that there are no parallel
ports to use.
EXAMPLE
^^^^^^^
::
int detect_device (void)
{
struct parport *port;
for (port = parport_enumerate ();
port != NULL;
port = port->next) {
/* Try to detect a device on the port... */
...
}
}
...
}
NOTES
^^^^^
parport_enumerate is deprecated; parport_register_driver should be
used instead.
SEE ALSO
^^^^^^^^
parport_register_driver, parport_unregister_driver
`parport_register_device()`와 장치 콜백 수명
357-535`parport_register_device()`는 특정 `struct parport`에 장치 드라이버 인스턴스를 등록합니다. 인자는 포트, 장치 이름, `preempt`·`wakeup`·`irq` 콜백, flags, 콜백에 돌려줄 `handle`입니다. 필요하지 않은 콜백은 `NULL`로 둘 수 있습니다.
`preempt` 콜백은 다른 드라이버가 포트를 요구할 때 현재 소유자가 포트를 양보할 수 있는지 묻습니다. 0을 반환하면 포트 소유권을 잃으며, non-zero를 반환하면 현재 작업 때문에 양보할 수 없다는 뜻입니다. 콜백이 0을 반환한 뒤에는 포트를 사용하기 전에 다시 claim해야 합니다.
`wakeup` 콜백은 포트가 사용 가능해졌을 때 호출됩니다. 이 콜백 안에서 `parport_claim()`을 호출하면 성공이 보장됩니다. `irq` 콜백은 포트 인터럽트가 발생했을 때 호출되며, `handle`은 세 콜백 모두에 드라이버의 사적 상태를 전달합니다.
`flags`에 `PARPORT_DEV_EXCL`을 지정하면 해당 포트에 다른 장치를 등록할 수 없는 독점 장치를 요청합니다. 성공 시 유효한 `struct pardevice *`를 반환하고 실패하면 `NULL`을 반환합니다. 원문의 toaster 예제는 콜백과 사적 구조체를 연결한 뒤 반환된 장치 핸들을 저장합니다.
`parport_unregister_device()`는 등록된 장치를 제거하고 전달된 핸들을 즉시 무효화합니다. claim한 장치를 해제하는 것은 올바른 사용법이 아니지만, 코어는 방어적으로 포트를 자동 release합니다. 호출 뒤에는 `dev`를 다시 참조해서는 안 됩니다.
공유 포트 중재 시 콜백이 소유권과 인터럽트 전달을 조정합니다.
parport_register_device - register to use a port
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
typedef int (*preempt_func) (void *handle);
typedef void (*wakeup_func) (void *handle);
typedef int (*irq_func) (int irq, void *handle, struct pt_regs *);
struct pardevice *parport_register_device(struct parport *port,
const char *name,
preempt_func preempt,
wakeup_func wakeup,
irq_func irq,
int flags,
void *handle);
DESCRIPTION
^^^^^^^^^^^
Use this function to register your device driver on a parallel port
(``port``). Once you have done that, you will be able to use
parport_claim and parport_release in order to use the port.
The (``name``) argument is the name of the device that appears in /proc
filesystem. The string must be valid for the whole lifetime of the
device (until parport_unregister_device is called).
This function will register three callbacks into your driver:
``preempt``, ``wakeup`` and ``irq``. Each of these may be NULL in order to
indicate that you do not want a callback.
When the ``preempt`` function is called, it is because another driver
wishes to use the parallel port. The ``preempt`` function should return
non-zero if the parallel port cannot be released yet -- if zero is
returned, the port is lost to another driver and the port must be
re-claimed before use.
The ``wakeup`` function is called once another driver has released the
port and no other driver has yet claimed it. You can claim the
parallel port from within the ``wakeup`` function (in which case the
claim is guaranteed to succeed), or choose not to if you don't need it
now.
If an interrupt occurs on the parallel port your driver has claimed,
the ``irq`` function will be called. (Write something about shared
interrupts here.)
The ``handle`` is a pointer to driver-specific data, and is passed to
the callback functions.
``flags`` may be a bitwise combination of the following flags:
===================== =================================================
Flag Meaning
===================== =================================================
PARPORT_DEV_EXCL The device cannot share the parallel port at all.
Use this only when absolutely necessary.
===================== =================================================
The typedefs are not actually defined -- they are only shown in order
to make the function prototype more readable.
The visible parts of the returned ``struct pardevice`` are::
struct pardevice {
struct parport *port; /* Associated port */
void *private; /* Device driver's 'handle' */
...
};
RETURN VALUE
^^^^^^^^^^^^
A ``struct pardevice *``: a handle to the registered parallel port
device that can be used for parport_claim, parport_release, etc.
ERRORS
^^^^^^
A return value of NULL indicates that there was a problem registering
a device on that port.
EXAMPLE
^^^^^^^
::
static int preempt (void *handle)
{
if (busy_right_now)
return 1;
must_reclaim_port = 1;
return 0;
}
static void wakeup (void *handle)
{
struct toaster *private = handle;
struct pardevice *dev = private->dev;
if (!dev) return; /* avoid races */
if (want_port)
parport_claim (dev);
}
static int toaster_detect (struct toaster *private, struct parport *port)
{
private->dev = parport_register_device (port, "toaster", preempt,
wakeup, NULL, 0,
private);
if (!private->dev)
/* Couldn't register with parport. */
return -EIO;
must_reclaim_port = 0;
busy_right_now = 1;
parport_claim_or_block (private->dev);
...
/* Don't need the port while the toaster warms up. */
busy_right_now = 0;
...
busy_right_now = 1;
if (must_reclaim_port) {
parport_claim_or_block (private->dev);
must_reclaim_port = 0;
}
...
}
SEE ALSO
^^^^^^^^
parport_unregister_device, parport_claim
parport_unregister_device - finish using a port
-----------------------------------------------
SYNPOPSIS
::
#include <linux/parport.h>
void parport_unregister_device (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
This function is the opposite of parport_register_device. After using
parport_unregister_device, ``dev`` is no longer a valid device handle.
You should not unregister a device that is currently claimed, although
if you do it will be released automatically.
EXAMPLE
^^^^^^^
::
...
kfree (dev->private); /* before we lose the pointer */
parport_unregister_device (dev);
...
SEE ALSO
^^^^^^^^
parport_unregister_driver
포트 claim, release와 일시 양보
536-669`parport_claim()`은 등록된 장치가 병렬 포트를 즉시 소유하도록 시도합니다. 성공하면 0, 다른 장치가 점유 중이면 `-EAGAIN`을 반환합니다. `parport_claim_or_block()`은 포트가 비어날 때까지 잠들 수 있으며, 즉시 얻으면 0, 기다렸다가 얻으면 양수, 기다릴 수 없거나 실패하면 `-EAGAIN`을 반환합니다.
포트를 claim한 동안에만 장치가 포트 연산을 수행해야 합니다. 작업을 마치면 `parport_release()`로 소유권을 반환합니다. 예제처럼 ECP 데이터를 쓴 뒤 release하면 대기 중인 다른 장치가 포트를 사용할 수 있습니다. 관련 모드 전환과 claim 상태를 일관되게 유지해야 합니다.
`parport_yield()`와 `parport_yield_blocking()`은 현재 소유자가 다른 드라이버에 포트를 잠시 빌려주도록 합니다. 전자는 block하지 않고 후자는 block할 수 있습니다. 반환값 0은 호출자가 계속 포트를 소유하며 block하지 않았다는 뜻이고, blocking 버전의 양수는 기다렸지만 다시 소유권을 확보했다는 뜻입니다.
yield 계열이 `-EAGAIN`을 반환하면 소유권이 실제로 다른 장치에 넘어간 것입니다. 이 상태에서는 포트를 건드리지 말고 `parport_claim()` 또는 `parport_claim_or_block()`으로 다시 확보해야 합니다.
parport_claim, parport_claim_or_block - claim the parallel port for a device
----------------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_claim (struct pardevice *dev);
int parport_claim_or_block (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
These functions attempt to gain control of the parallel port on which
``dev`` is registered. ``parport_claim`` does not block, but
``parport_claim_or_block`` may do. (Put something here about blocking
interruptibly or non-interruptibly.)
You should not try to claim a port that you have already claimed.
RETURN VALUE
^^^^^^^^^^^^
A return value of zero indicates that the port was successfully
claimed, and the caller now has possession of the parallel port.
If ``parport_claim_or_block`` blocks before returning successfully, the
return value is positive.
ERRORS
^^^^^^
========== ==========================================================
-EAGAIN The port is unavailable at the moment, but another attempt
to claim it may succeed.
========== ==========================================================
SEE ALSO
^^^^^^^^
parport_release
parport_release - release the parallel port
-------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
void parport_release (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
Once a parallel port device has been claimed, it can be released using
``parport_release``. It cannot fail, but you should not release a
device that you do not have possession of.
EXAMPLE
^^^^^^^
::
static size_t write (struct pardevice *dev, const void *buf,
size_t len)
{
...
written = dev->port->ops->write_ecp_data (dev->port, buf,
len);
parport_release (dev);
...
}
SEE ALSO
^^^^^^^^
change_mode, parport_claim, parport_claim_or_block, parport_yield
parport_yield, parport_yield_blocking - temporarily release a parallel port
---------------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_yield (struct pardevice *dev)
int parport_yield_blocking (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
When a driver has control of a parallel port, it may allow another
driver to temporarily ``borrow`` it. ``parport_yield`` does not block;
``parport_yield_blocking`` may do.
RETURN VALUE
^^^^^^^^^^^^
A return value of zero indicates that the caller still owns the port
and the call did not block.
A positive return value from ``parport_yield_blocking`` indicates that
the caller still owns the port and the call blocked.
A return value of -EAGAIN indicates that the caller no longer owns the
port, and it must be re-claimed before use.
ERRORS
^^^^^^
========= ==========================================================
-EAGAIN Ownership of the parallel port was given away.
========= ==========================================================
SEE ALSO
^^^^^^^^
parport_release
상태선 대기, 이벤트와 IEEE 1284 협상
670-801`parport_wait_peripheral()`은 status register에서 `mask`로 고른 선들이 `val`의 값과 일치할 때까지 최대 35ms 기다립니다. signal이 pending이면 `-EINTR`, 조건이 맞으면 0, 35ms가 지나면 1을 반환합니다.
`parport_poll_peripheral()`은 같은 조건을 `usec` 마이크로초 동안 polling합니다. 반환 규약도 `-EINTR`, 0, 1로 같지만 timeout 길이를 호출자가 정합니다. 이 두 함수의 양수 1은 errno가 아니라 시간 초과를 뜻합니다.
`parport_wait_event()`는 인터럽트 같은 포트 이벤트를 `timeout` jiffies 동안 기다립니다. 0은 성공, 음수는 가능한 한 빨리 종료해야 하는 오류, 양수는 timeout입니다.
`parport_negotiate()`는 지정한 `mode`로 IEEE 1284 협상을 수행합니다. 0은 handshake가 성공했고 주변장치와 모드가 모두 사용 가능함을 뜻합니다. -1은 handshake 실패로, 장치가 IEEE 1284 호환이 아니거나 아예 없을 수 있습니다. 1은 IEEE 1284 장치는 확인됐지만 요청한 모드는 사용할 수 없다는 뜻입니다.
parport_wait_peripheral - wait for status lines, up to 35ms
-----------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_wait_peripheral (struct parport *port,
unsigned char mask,
unsigned char val);
DESCRIPTION
^^^^^^^^^^^
Wait for the status lines in mask to match the values in val.
RETURN VALUE
^^^^^^^^^^^^
======== ==========================================================
-EINTR a signal is pending
0 the status lines in mask have values in val
1 timed out while waiting (35ms elapsed)
======== ==========================================================
SEE ALSO
^^^^^^^^
parport_poll_peripheral
parport_poll_peripheral - wait for status lines, in usec
--------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_poll_peripheral (struct parport *port,
unsigned char mask,
unsigned char val,
int usec);
DESCRIPTION
^^^^^^^^^^^
Wait for the status lines in mask to match the values in val.
RETURN VALUE
^^^^^^^^^^^^
======== ==========================================================
-EINTR a signal is pending
0 the status lines in mask have values in val
1 timed out while waiting (usec microseconds have elapsed)
======== ==========================================================
SEE ALSO
^^^^^^^^
parport_wait_peripheral
parport_wait_event - wait for an event on a port
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_wait_event (struct parport *port, signed long timeout)
DESCRIPTION
^^^^^^^^^^^
Wait for an event (e.g. interrupt) on a port. The timeout is in
jiffies.
RETURN VALUE
^^^^^^^^^^^^
======= ==========================================================
0 success
<0 error (exit as soon as possible)
>0 timed out
======= ==========================================================
parport_negotiate - perform IEEE 1284 negotiation
-------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_negotiate (struct parport *, int mode);
DESCRIPTION
^^^^^^^^^^^
Perform IEEE 1284 negotiation.
RETURN VALUE
^^^^^^^^^^^^
======= ==========================================================
0 handshake OK; IEEE 1284 peripheral and mode available
-1 handshake failed; peripheral not compliant (or none present)
1 handshake OK; IEEE 1284 peripheral present but mode not
available
======= ==========================================================
SEE ALSO
^^^^^^^^
parport_read, parport_write
현재 모드 전송과 장치 번호 기반 열기
802-921`parport_read()`는 현재 IEEE 1284 전송 모드로 장치에서 `buf`에 최대 `len` 바이트를 읽습니다. 역방향 데이터 전송을 지원하는 모드에서만 동작합니다. 음수는 오류 코드이고, 0 이상의 값은 실제 전송한 바이트 수입니다.
`parport_write()`는 현재 IEEE 1284 전송 모드로 `buf`의 데이터를 장치에 씁니다. 순방향 데이터 전송을 지원하는 모드에서만 동작하며, 반환 규약은 `parport_read()`와 같습니다. 두 함수 모두 먼저 `parport_negotiate()`로 알맞은 모드를 선택한 상태에서 사용해야 합니다.
`parport_open()`은 `struct parport *` 대신 0부터 시작하는 장치 번호 `devnum`을 받아 장치를 등록한다는 점을 제외하면 `parport_register_device()`와 같습니다. 지정한 번호에 대응하는 장치가 없거나 등록에 실패하면 `NULL`을 반환합니다.
`parport_close()`는 `parport_open()`으로 얻은 장치를 닫는 짝 함수이며, 장치 등록 방식의 `parport_unregister_device()`에 해당합니다. 열린 핸들의 수명과 claim 상태를 정리한 뒤 호출해야 합니다.
장치 번호를 핸들로 바꾸고 모드를 협상한 뒤 전송하고 닫습니다.
parport_read - read data from device
------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
ssize_t parport_read (struct parport *, void *buf, size_t len);
DESCRIPTION
^^^^^^^^^^^
Read data from device in current IEEE 1284 transfer mode. This only
works for modes that support reverse data transfer.
RETURN VALUE
^^^^^^^^^^^^
If negative, an error code; otherwise the number of bytes transferred.
SEE ALSO
^^^^^^^^
parport_write, parport_negotiate
parport_write - write data to device
------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
ssize_t parport_write (struct parport *, const void *buf, size_t len);
DESCRIPTION
^^^^^^^^^^^
Write data to device in current IEEE 1284 transfer mode. This only
works for modes that support forward data transfer.
RETURN VALUE
^^^^^^^^^^^^
If negative, an error code; otherwise the number of bytes transferred.
SEE ALSO
^^^^^^^^
parport_read, parport_negotiate
parport_open - register device for particular device number
-----------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct pardevice *parport_open (int devnum, const char *name,
int (*pf) (void *),
void (*kf) (void *),
void (*irqf) (int, void *,
struct pt_regs *),
int flags, void *handle);
DESCRIPTION
^^^^^^^^^^^
This is like parport_register_device but takes a device number instead
of a pointer to a struct parport.
RETURN VALUE
^^^^^^^^^^^^
See parport_register_device. If no device is associated with devnum,
NULL is returned.
SEE ALSO
^^^^^^^^
parport_register_device
parport_close - unregister device for particular device number
--------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
void parport_close (struct pardevice *dev);
DESCRIPTION
^^^^^^^^^^^
This is the equivalent of parport_unregister_device for parport_open.
SEE ALSO
^^^^^^^^
parport_unregister_device, parport_open
IEEE 1284 Device ID, 좌표와 class 검색
922-1055`parport_device_id()`는 장치 번호 `devnum`에 연결된 IEEE 1284 Device ID를 `buffer`에 가져옵니다. 음수는 오류이고, 0 이상의 반환값은 buffer에서 Device ID가 차지하는 바이트 수입니다.
Device ID 형식은 `[length][ID]`입니다. 첫 두 바이트는 전체 Device ID를 포함하는 길이를 big-endian으로 담으며, 뒤의 ID는 `key:value;` 쌍의 연속입니다. 실제 장치에는 형식이 잘못된 Device ID가 많으므로 파서는 누락·오류를 견고하게 처리해야 합니다.
`parport_device_coords()`는 0 기반 장치 번호를 `(port, multiplexor, daisy chain address)` 좌표로 변환합니다. 성공 시 0을 반환하며 결과는 `*parport`, `*mux`, `*daisy`에 기록됩니다.
`parport_find_class()`는 지정한 `parport_device_class`의 다음 장치를 찾습니다. 검색은 `from + 1`에서 시작하고, 찾으면 장치 번호, 없으면 -1을 반환합니다. class에는 `PARPORT_CLASS_LEGACY`, `PRINTER`, `MODEM`, `NET`, `HDC`, `PCMCIA`, `MEDIA`, `FDC`, `PORTS`, `SCANNER`, `DIGCAM`, `OTHER`, `UNSPEC`, `SCSIADAPTER`가 있습니다.
모든 digital camera를 순회하는 원문 예제처럼 첫 `from`을 -1로 두고, 반환된 번호를 다음 호출의 `from`으로 넘깁니다. 각 번호는 `parport_open()`으로 열 수 있습니다.
parport_device_id - obtain IEEE 1284 Device ID
----------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
ssize_t parport_device_id (int devnum, char *buffer, size_t len);
DESCRIPTION
^^^^^^^^^^^
Obtains the IEEE 1284 Device ID associated with a given device.
RETURN VALUE
^^^^^^^^^^^^
If negative, an error code; otherwise, the number of bytes of buffer
that contain the device ID. The format of the device ID is as
follows::
[length][ID]
The first two bytes indicate the inclusive length of the entire Device
ID, and are in big-endian order. The ID is a sequence of pairs of the
form::
key:value;
NOTES
^^^^^
Many devices have ill-formed IEEE 1284 Device IDs.
SEE ALSO
^^^^^^^^
parport_find_class, parport_find_device
parport_device_coords - convert device number to device coordinates
-------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_device_coords (int devnum, int *parport, int *mux,
int *daisy);
DESCRIPTION
^^^^^^^^^^^
Convert between device number (zero-based) and device coordinates
(port, multiplexor, daisy chain address).
RETURN VALUE
^^^^^^^^^^^^
Zero on success, in which case the coordinates are (``*parport``, ``*mux``,
``*daisy``).
SEE ALSO
^^^^^^^^
parport_open, parport_device_id
parport_find_class - find a device by its class
-----------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
typedef enum {
PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */
PARPORT_CLASS_PRINTER,
PARPORT_CLASS_MODEM,
PARPORT_CLASS_NET,
PARPORT_CLASS_HDC, /* Hard disk controller */
PARPORT_CLASS_PCMCIA,
PARPORT_CLASS_MEDIA, /* Multimedia device */
PARPORT_CLASS_FDC, /* Floppy disk controller */
PARPORT_CLASS_PORTS,
PARPORT_CLASS_SCANNER,
PARPORT_CLASS_DIGCAM,
PARPORT_CLASS_OTHER, /* Anything else */
PARPORT_CLASS_UNSPEC, /* No CLS field in ID */
PARPORT_CLASS_SCSIADAPTER
} parport_device_class;
int parport_find_class (parport_device_class cls, int from);
DESCRIPTION
^^^^^^^^^^^
Find a device by class. The search starts from device number from+1.
RETURN VALUE
^^^^^^^^^^^^
The device number of the next device in that class, or -1 if no such
device exists.
NOTES
^^^^^
Example usage::
int devnum = -1;
while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, devnum)) != -1) {
struct pardevice *dev = parport_open (devnum, ...);
...
}
SEE ALSO
^^^^^^^^
parport_find_device, parport_open, parport_device_id
제조사·모델 검색과 inactivity timeout
1056-1144`parport_find_device()`는 IEEE 1284 Device ID의 제조사 `mfg`와 모델 `mdl`이 일치하는 장치를 찾습니다. 검색은 `from + 1`에서 시작하며, 다음 일치 장치 번호를 반환하거나 더 없으면 -1을 반환합니다. 원문은 `IOMEGA`, `ZIP+`를 반복 검색해 각각 `parport_open()`하는 예를 보입니다.
`parport_set_timeout()`은 등록된 장치의 inactivity timeout을 jiffies 단위로 설정하고 이전 값을 반환합니다. 설정은 다시 바꿀 때까지 장치에 유지됩니다.
일부 `port->ops->xxx_read/write_yyy` 전송은 주변장치 응답 지연 때문에 오래 걸릴 수 있습니다. 주변장치가 `inactivity` jiffies 동안 응답하지 않으면 timeout이 발생하고 blocking 함수가 반환합니다.
0 jiffies는 특별합니다. 연산은 block하지 않고 하드웨어를 알 수 없는 상태에 남기지 않는 범위에서 가능한 만큼만 수행해야 합니다. 인터럽트 handler 안에서 포트 연산을 수행해야 한다면 timeout을 0으로 설정해야 합니다.
parport_find_device - find a device by its class
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
int parport_find_device (const char *mfg, const char *mdl, int from);
DESCRIPTION
^^^^^^^^^^^
Find a device by vendor and model. The search starts from device
number from+1.
RETURN VALUE
^^^^^^^^^^^^
The device number of the next device matching the specifications, or
-1 if no such device exists.
NOTES
^^^^^
Example usage::
int devnum = -1;
while ((devnum = parport_find_device ("IOMEGA", "ZIP+", devnum)) != -1) {
struct pardevice *dev = parport_open (devnum, ...);
...
}
SEE ALSO
^^^^^^^^
parport_find_class, parport_open, parport_device_id
parport_set_timeout - set the inactivity timeout
------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
long parport_set_timeout (struct pardevice *dev, long inactivity);
DESCRIPTION
^^^^^^^^^^^
Set the inactivity timeout, in jiffies, for a registered device. The
previous timeout is returned.
RETURN VALUE
^^^^^^^^^^^^
The previous timeout, in jiffies.
NOTES
^^^^^
Some of the port->ops functions for a parport may take time, owing to
delays at the peripheral. After the peripheral has not responded for
``inactivity`` jiffies, a timeout will occur and the blocking function
will return.
A timeout of 0 jiffies is a special case: the function must do as much
as it can without blocking or leaving the hardware in an unknown
state. If port operations are performed from within an interrupt
handler, for instance, a timeout of 0 jiffies should be used.
Once set for a registered device, the timeout will remain at the set
value until set again.
SEE ALSO
^^^^^^^^
port->ops->xxx_read/write_yyy
기본 data·status register 연산
1145-1248이 절부터의 함수는 포트를 담당하는 저수준 드라이버가 `struct parport_operations`에 구현합니다. 상위 parport 코어와 장치 드라이버는 이 `port->ops` 테이블을 통해 아키텍처별 레지스터나 하드웨어 엔진을 사용합니다.
`port->ops->read_data()`는 조건에 따라 데이터 핀 또는 마지막 출력값을 읽습니다. `port->modes`에 `PARPORT_MODE_TRISTATE`가 있고 control register의 `PARPORT_CONTROL_DIRECTION` 비트가 설정돼 있으면 데이터 핀 값을 반환합니다. TRISTATE는 지원하지만 방향 비트가 꺼져 있으면 마지막으로 data register에 쓴 값일 수 있으며, 그 밖의 경우 반환값은 정의되지 않습니다.
`port->ops->write_data()`는 data register에 바이트를 씁니다. 구현에 따라 STROBE pulse 같은 부수 효과가 생길 수 있으므로 단순 메모리 저장처럼 취급해서는 안 됩니다.
`port->ops->read_status()`는 status register 비트마스크를 반환합니다. 표준 비트는 `PARPORT_STATUS_ERROR`(printer fault, `nFault`), `PARPORT_STATUS_SELECT`(on-line, `Select`), `PARPORT_STATUS_PAPEROUT`(no paper, `PError`), `PARPORT_STATUS_ACK`(handshake, `nAck`), `PARPORT_STATUS_BUSY`(busy, `Busy`)이며 다른 비트도 함께 설정될 수 있습니다.
PORT FUNCTIONS
==============
The functions in the port->ops structure (struct parport_operations)
are provided by the low-level driver responsible for that port.
port->ops->read_data - read the data register
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*read_data) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
If port->modes contains the PARPORT_MODE_TRISTATE flag and the
PARPORT_CONTROL_DIRECTION bit in the control register is set, this
returns the value on the data pins. If port->modes contains the
PARPORT_MODE_TRISTATE flag and the PARPORT_CONTROL_DIRECTION bit is
not set, the return value _may_ be the last value written to the data
register. Otherwise the return value is undefined.
SEE ALSO
^^^^^^^^
write_data, read_status, write_control
port->ops->write_data - write the data register
-----------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*write_data) (struct parport *port, unsigned char d);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes to the data register. May have side-effects (a STROBE pulse,
for instance).
SEE ALSO
^^^^^^^^
read_data, read_status, write_control
port->ops->read_status - read the status register
-------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*read_status) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads from the status register. This is a bitmask:
- PARPORT_STATUS_ERROR (printer fault, "nFault")
- PARPORT_STATUS_SELECT (on-line, "Select")
- PARPORT_STATUS_PAPEROUT (no paper, "PError")
- PARPORT_STATUS_ACK (handshake, "nAck")
- PARPORT_STATUS_BUSY (busy, "Busy")
There may be other bits set.
SEE ALSO
^^^^^^^^
read_data, write_data, write_control
control register 읽기·쓰기와 선택 비트 변경
1249-1350`port->ops->read_control()`은 `write_control()` 또는 `frob_control()`이 마지막으로 기록한 control register 값을 반환합니다. 실제 포트 read는 수행하지 않으며, 저수준 드라이버가 유지하는 소프트웨어 사본을 읽습니다.
`port->ops->write_control()`은 control register 비트마스크를 기록합니다. 정의된 선은 `PARPORT_CONTROL_STROBE`(`nStrobe`), `PARPORT_CONTROL_AUTOFD`(`nAutoFd`), `PARPORT_CONTROL_INIT`(`nInit`), `PARPORT_CONTROL_SELECT`(`nSelectIn`)입니다. 신호 이름의 `n`과 원문의 윗줄 표시는 active-low 신호임을 나타냅니다.
`port->ops->frob_control()`은 현재 control 값에서 `mask` 비트를 대상으로 `val`과 exclusive-or한 결과를 다시 기록하는 선택적 갱신 연산입니다. 의미상 read-modify-write이지만 control port 읽기를 지원하지 않는 하드웨어를 위해 소프트웨어 사본을 사용하므로 실제 포트 접근은 한 번뿐입니다.
여러 control 선을 바꾸는 코드에서는 전체 값을 덮어쓸지 `frob_control()`로 특정 비트만 변경할지 명확히 선택해야 합니다. `read_control()`이 물리 핀을 샘플링하지 않는다는 점도 진단 코드에서 중요합니다.
port->ops->read_control - read the control register
---------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*read_control) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Returns the last value written to the control register (either from
write_control or frob_control). No port access is performed.
SEE ALSO
^^^^^^^^
read_data, write_data, read_status, write_control
port->ops->write_control - write the control register
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*write_control) (struct parport *port, unsigned char s);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes to the control register. This is a bitmask::
_______
- PARPORT_CONTROL_STROBE (nStrobe)
_______
- PARPORT_CONTROL_AUTOFD (nAutoFd)
_____
- PARPORT_CONTROL_INIT (nInit)
_________
- PARPORT_CONTROL_SELECT (nSelectIn)
SEE ALSO
^^^^^^^^
read_data, write_data, read_status, frob_control
port->ops->frob_control - write control register bits
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
unsigned char (*frob_control) (struct parport *port,
unsigned char mask,
unsigned char val);
...
};
DESCRIPTION
^^^^^^^^^^^
This is equivalent to reading from the control register, masking out
the bits in mask, exclusive-or'ing with the bits in val, and writing
the result to the control register.
As some ports don't allow reads from the control port, a software copy
of its contents is maintained, so frob_control is in fact only one
port access.
SEE ALSO
^^^^^^^^
read_data, write_data, read_status, write_control
인터럽트와 데이터 버스 방향 제어
1351-1468`port->ops->enable_irq()`는 아키텍처가 정한 적절한 시점에 병렬 포트 하드웨어가 인터럽트를 생성하도록 설정합니다. PC 아키텍처에서는 보통 `nAck`의 rising edge에서 인터럽트가 발생합니다.
`port->ops->disable_irq()`는 병렬 포트 하드웨어가 인터럽트를 생성하지 않도록 합니다. 이 연산은 인터럽트 자체를 mask하는 것이 아니라 포트의 발생 기능을 끄는 것입니다. IRQ controller 수준의 masking과 구분해야 합니다.
`port->ops->data_forward()`는 data line driver를 활성화하여 host에서 peripheral로 8-bit 통신을 수행하게 합니다. `port->ops->data_reverse()`는 `port->modes`에 `PARPORT_MODE_TRISTATE`가 있을 때 data bus를 high-impedance 상태로 두어 peripheral에서 host로 데이터를 받을 수 있게 합니다.
전송 방향을 바꿀 때에는 현재 모드와 주변장치 handshake를 함께 고려해야 합니다. TRISTATE 지원이 없는 포트에서 역방향 전환을 가정하면 안 됩니다.
포트 하드웨어의 발생 제어와 data driver 방향을 서로 독립적으로 다룹니다.
port->ops->enable_irq - enable interrupt generation
---------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*enable_irq) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
The parallel port hardware is instructed to generate interrupts at
appropriate moments, although those moments are
architecture-specific. For the PC architecture, interrupts are
commonly generated on the rising edge of nAck.
SEE ALSO
^^^^^^^^
disable_irq
port->ops->disable_irq - disable interrupt generation
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*disable_irq) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
The parallel port hardware is instructed not to generate interrupts.
The interrupt itself is not masked.
SEE ALSO
^^^^^^^^
enable_irq
port->ops->data_forward - enable data drivers
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*data_forward) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Enables the data line drivers, for 8-bit host-to-peripheral
communications.
SEE ALSO
^^^^^^^^
data_reverse
port->ops->data_reverse - tristate the buffer
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
void (*data_reverse) (struct parport *port);
...
};
DESCRIPTION
^^^^^^^^^^^
Places the data bus in a high impedance state, if port->modes has the
PARPORT_MODE_TRISTATE bit set.
SEE ALSO
^^^^^^^^
data_forward
EPP data 전송과 address 쓰기
1469-1584`port->ops->epp_write_data()`는 EPP mode에서 `buf`의 `len` 바이트를 data cycle로 쓰고 실제 쓴 바이트 수를 반환합니다. `port->ops->epp_read_data()`는 EPP data cycle로 읽어 `buf`에 저장하고 실제 읽은 바이트 수를 반환합니다.
두 data 연산의 `flags`에는 `PARPORT_EPP_FAST`를 bitwise OR하여 지정할 수 있습니다. 일부 칩의 16-bit 또는 32-bit register를 이용해 빠르게 전송하지만, 전송이 timeout되면 반환한 바이트 수가 신뢰할 수 없을 수 있습니다.
`port->ops->epp_write_addr()`는 각 8-bit EPP address를 쓰고 처리한 address 수를 반환합니다. 이 함수에도 `PARPORT_EPP_FAST`가 정의돼 있지만, 원문은 address 연산에 fast flag가 의미가 있는지 의문을 그대로 남깁니다.
EPP data와 address cycle은 같은 byte buffer 형식을 사용하더라도 프로토콜에서 구별됩니다. 호출자는 peripheral의 register 선택에는 address 연산을, payload에는 data 연산을 사용해야 합니다.
port->ops->epp_write_data - write EPP data
------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_write_data) (struct parport *port, const void *buf,
size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes data in EPP mode, and returns the number of bytes written.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
SEE ALSO
^^^^^^^^
epp_read_data, epp_write_addr, epp_read_addr
port->ops->epp_read_data - read EPP data
----------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_read_data) (struct parport *port, void *buf,
size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads data in EPP mode, and returns the number of bytes read.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
SEE ALSO
^^^^^^^^
epp_write_data, epp_write_addr, epp_read_addr
port->ops->epp_write_addr - write EPP address
---------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_write_addr) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes EPP addresses (8 bits each), and returns the number written.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
(Does PARPORT_EPP_FAST make sense for this function?)
SEE ALSO
^^^^^^^^
epp_write_data, epp_read_data, epp_read_addr
EPP address 읽기
1585-1624`port->ops->epp_read_addr()`는 EPP address cycle을 사용해 각각 8-bit인 address들을 `buf`에 읽습니다. 반환값은 실제로 읽은 address 수입니다.
`flags`는 bitwise OR한 옵션을 받으며 현재 문서화된 값은 `PARPORT_EPP_FAST`입니다. 일부 칩의 16-bit·32-bit register로 빠른 전송을 사용할 수 있지만 timeout이 발생하면 반환값이 신뢰할 수 없을 수 있습니다.
원문은 `epp_write_addr()`와 마찬가지로 address 읽기에서 `PARPORT_EPP_FAST`가 실제로 의미가 있는지 열린 질문으로 남깁니다. 저수준 드라이버 구현은 하드웨어 동작을 확인하고, 상위 호출자는 부분 전송과 불확실한 count를 고려해야 합니다.
port->ops->epp_read_addr - read EPP address
-------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*epp_read_addr) (struct parport *port, void *buf,
size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads EPP addresses (8 bits each), and returns the number read.
The ``flags`` parameter may be one or more of the following,
bitwise-or'ed together:
======================= =================================================
PARPORT_EPP_FAST Use fast transfers. Some chips provide 16-bit and
32-bit registers. However, if a transfer
times out, the return value may be unreliable.
======================= =================================================
(Does PARPORT_EPP_FAST make sense for this function?)
SEE ALSO
^^^^^^^^
epp_write_data, epp_read_data, epp_write_addr
ECP data와 address block 전송
1625-1732`port->ops->ecp_write_data()`는 ECP data block을 쓰고 실제 쓴 바이트 수를 반환합니다. `port->ops->ecp_read_data()`는 ECP data block을 읽고 실제 읽은 바이트 수를 반환합니다. 두 함수 모두 `flags` 인자를 받지만 이 API에서는 무시합니다.
ECP read가 반환한 뒤에도 하드웨어 FIFO에 읽지 않은 데이터가 남아 있을 수 있습니다. 원문은 FIFO를 멈춰 이를 방지할 방법이 있는지 질문을 남깁니다. 따라서 반환 count만으로 peripheral과 FIFO가 완전히 비었다고 단정해서는 안 됩니다.
`port->ops->ecp_write_addr()`는 ECP address block을 쓰고 쓴 바이트 수를 반환하며 `flags`는 무시합니다. 구현이 FIFO를 사용한다면 FIFO가 완전히 빌 때까지 반환해서는 안 됩니다.
원문의 관련 항목에는 `ecp_write_block` 표기가 있지만 실제 이 절의 함수 이름은 `ecp_write_data`입니다. 번역에서는 원문 symbol을 보존하면서 구현자가 함수 포인터 이름을 혼동하지 않도록 구분합니다.
Write-address는 FIFO drain을 보장하지만 read-data 뒤에는 잔여 데이터가 있을 수 있습니다.
port->ops->ecp_write_data - write a block of ECP data
-----------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*ecp_write_data) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes a block of ECP data. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes written.
SEE ALSO
^^^^^^^^
ecp_read_data, ecp_write_addr
port->ops->ecp_read_data - read a block of ECP data
---------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*ecp_read_data) (struct parport *port,
void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads a block of ECP data. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes read. NB. There may be more unread data in a
FIFO. Is there a way of stunning the FIFO to prevent this?
SEE ALSO
^^^^^^^^
ecp_write_block, ecp_write_addr
port->ops->ecp_write_addr - write a block of ECP addresses
----------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*ecp_write_addr) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes a block of ECP addresses. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes written.
NOTES
^^^^^
This may use a FIFO, and if so shall not return until the FIFO is empty.
SEE ALSO
^^^^^^^^
ecp_read_data, ecp_write_data
Nibble·byte·compatibility mode block 전송
1733-1832`port->ops->nibble_read_data()`는 IEEE 1284 nibble mode로 data block을 읽습니다. 전송은 nibble 단위 프로토콜을 사용하지만 반환값은 완성된 전체 바이트 수이며 `flags`는 무시합니다.
`port->ops->byte_read_data()`는 byte mode로 data block을 읽고 실제 읽은 바이트 수를 반환합니다. 이 연산도 `flags`를 무시하며, 역방향 byte 전송에는 포트의 양방향 데이터 버스 지원이 필요합니다.
`port->ops->compat_write_data()`는 compatibility mode로 data block을 쓰고 실제 쓴 바이트 수를 반환합니다. `flags`는 무시됩니다. 이 세 함수는 EPP/ECP 하드웨어가 없어도 IEEE 1284의 기본 역방향·순방향 경로를 구성합니다.
모든 block 함수에서 요청 길이와 반환 count가 다를 수 있으므로 호출자는 부분 전송을 처리해야 합니다. mode를 협상하고 포트를 claim한 상태에서 알맞은 방향 연산을 선택해야 합니다.
port->ops->nibble_read_data - read a block of data in nibble mode
-----------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*nibble_read_data) (struct parport *port,
void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads a block of data in nibble mode. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of whole bytes read.
SEE ALSO
^^^^^^^^
byte_read_data, compat_write_data
port->ops->byte_read_data - read a block of data in byte mode
-------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*byte_read_data) (struct parport *port,
void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Reads a block of data in byte mode. The ``flags`` parameter is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes read.
SEE ALSO
^^^^^^^^
nibble_read_data, compat_write_data
port->ops->compat_write_data - write a block of data in compatibility mode
--------------------------------------------------------------------------
SYNOPSIS
^^^^^^^^
::
#include <linux/parport.h>
struct parport_operations {
...
size_t (*compat_write_data) (struct parport *port,
const void *buf, size_t len, int flags);
...
};
DESCRIPTION
^^^^^^^^^^^
Writes a block of data in compatibility mode. The ``flags`` parameter
is ignored.
RETURN VALUE
^^^^^^^^^^^^
The number of bytes written.
SEE ALSO
^^^^^^^^
nibble_read_data, byte_read_data
요약과 해설
parport-lowlevel.rst:1-1832이 문서는 Linux `parport` 공유 계층의 전체 저수준 계약을 설명합니다. 장치 드라이버는 포트 알림과 `pardevice`를 등록하고, claim·release·yield로 소유권을 조정한 뒤 IEEE 1284 모드를 협상해 전송합니다. 포트 드라이버는 `struct parport_operations`에 레지스터, IRQ, 방향, EPP·ECP·기본 block 전송을 구현합니다.
안전한 호출 순서는 수명 확보, 포트 claim, mode와 timeout 설정, 전송, release입니다. 특히 양수 반환이 성공 후 대기 또는 timeout을 뜻하는 API, `-EAGAIN` 뒤 소유권 재확보, 0-jiffy의 non-blocking 규칙, EPP fast timeout과 ECP FIFO 조건을 구분해야 합니다.
상위 장치 API와 하위 포트 연산의 경계를 따라 읽으면 구현 책임이 선명해집니다.