summaryrefslogtreecommitdiffstats
path: root/drivers/parport
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
commit46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch)
tree3b9b51fc482e729f663d25333e77fbed9aaa939a /drivers/parport
parent31dc59d503a02e84c4de98826452acaeb56dc15a (diff)
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'drivers/parport')
-rw-r--r--drivers/parport/ChangeLog5
-rw-r--r--drivers/parport/parport_pc.c27
-rw-r--r--drivers/parport/parport_sunbpp.c4
-rw-r--r--drivers/parport/share.c235
4 files changed, 245 insertions, 26 deletions
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
index e8bd316e6..b2f122af0 100644
--- a/drivers/parport/ChangeLog
+++ b/drivers/parport/ChangeLog
@@ -1,3 +1,8 @@
+2000-03-27 Tim Waugh <twaugh@redhat.com>
+
+ * parport_pc.c (parport_pc_ecp_read_block_pio): Correct operation
+ when peripheral is trying to send data when we stop listening.
+
2000-03-22 Tim Waugh <twaugh@redhat.com>
* init.c (parport_setup): Fix return value.
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 16b5ea3fe..5b912d3ef 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -178,9 +178,6 @@ static int get_fifo_residue (struct parport *p)
int cnfga;
const struct parport_pc_private *priv = p->physport->private_data;
- /* Prevent further data transfer. */
- frob_econtrol (p, 0xe0, ECR_TST << 5);
-
/* Adjust for the contents of the FIFO. */
for (residue = priv->fifo_depth; ; residue--) {
if (inb (ECONTROL (p)) & 0x2)
@@ -862,7 +859,8 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port,
length, flags);
/* Switch to reverse mode if necessary. */
- if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {
+ if ((port->ieee1284.phase != IEEE1284_PH_REV_IDLE) &&
+ (port->ieee1284.phase != IEEE1284_PH_REV_DATA)) {
/* Event 38: Set nAutoFd low */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
@@ -879,7 +877,7 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port,
parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
}
- /* Set up ECP parallel port mode.*/
+ /* Set up ECP FIFO mode.*/
parport_pc_data_reverse (port); /* Must be in PS2 mode */
parport_pc_frob_control (port,
PARPORT_CONTROL_STROBE |
@@ -951,15 +949,24 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port,
left--;
}
+ port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+
+ /* Go to forward idle mode to shut the peripheral up. */
+ parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
+ parport_wait_peripheral (port,
+ PARPORT_STATUS_PAPEROUT,
+ PARPORT_STATUS_PAPEROUT);
+ port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
/* Finish up. */
- if (change_mode (port, ECR_PS2) == -EBUSY) {
+ {
int lost = get_fifo_residue (port);
- printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", port->name,
- lost);
+ if (lost)
+ /* Shouldn't happen with compliant peripherals. */
+ printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n",
+ port->name, lost);
}
- port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-
return length - left;
}
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index c1cdd3d9a..6cafbc11a 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -1,4 +1,4 @@
-/* $Id: parport_sunbpp.c,v 1.9 1999/10/14 05:59:43 ecd Exp $
+/* $Id: parport_sunbpp.c,v 1.10 2000/03/27 01:47:56 anton Exp $
* Parallel-port routines for Sun architecture
*
* Author: Derrick J. Brashear <shadow@dementia.org>
@@ -335,6 +335,8 @@ static int __init init_one_port(struct sbus_dev *sdev)
return 0;
}
+ p->size = size;
+
dprintk(("init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p));
if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index fe5ea143b..27cd907e1 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -103,6 +103,19 @@ static void get_lowlevel_driver (void)
request_module ("parport_lowlevel");
}
+/**
+ * parport_register_driver - register a parallel port device driver
+ * @drv: structure describing the driver
+ *
+ * This can be called by a parallel port device driver in order to
+ * receive notifications about ports being found in the system, as
+ * well as ports no longer available.
+ *
+ * The @drv structure is allocated by the caller and must not be
+ * deallocated until after calling parport_unregister_driver().
+ *
+ * Returns 0 on success. Currently it always succeeds.
+ **/
int parport_register_driver (struct parport_driver *drv)
{
struct parport *port;
@@ -121,6 +134,23 @@ int parport_register_driver (struct parport_driver *drv)
return 0;
}
+/**
+ * parport_unregister_driver - deregister a parallel port device driver
+ * @arg: structure describing the driver that was given to
+ * parport_register_driver()
+ *
+ * This should be called by a parallel port device driver that has
+ * registered itself using parport_register_driver() when it is about
+ * to be unloaded.
+ *
+ * When it returns, the driver's attach() routine will no longer be
+ * called, and for each port that attach() was called for, the
+ * detach() routine will hae been called.
+ *
+ * If the caller's attach() function can block, it is their
+ * responsibility to make sure to wait for it to exit before
+ * unloading.
+ **/
void parport_unregister_driver (struct parport_driver *arg)
{
struct parport_driver *drv = driver_chain, *olddrv = NULL;
@@ -149,8 +179,17 @@ void parport_unregister_driver (struct parport_driver *arg)
}
}
-/* Return a list of all the ports we know about. This function shouldn't
- * really be used -- use parport_register_driver instead. */
+/**
+ * parport_enumerate - return a list of the system's parallel ports
+ *
+ * This returns the head of the list of parallel ports in the system.
+ * The structure that is returned describes the first port in the
+ * list, and its 'next' member points to the next port, or %NULL if
+ * it's the last port.
+ *
+ * If there are no parallel ports in the system, parport_enumerate()
+ * will return %NULL.
+ **/
struct parport *parport_enumerate(void)
{
if (!portlist)
@@ -159,6 +198,33 @@ struct parport *parport_enumerate(void)
return portlist;
}
+/**
+ * parport_register_port - register a parallel port
+ * @base: base I/O address
+ * @irq: IRQ line
+ * @dma: DMA channel
+ * @ops: pointer to the port driver's port operations structure
+ *
+ * When a parallel port (lowlevel) driver finds a port that should be
+ * made available to parallel port device drivers, it should call
+ * parport_register_port(). The @base, @irq, and @dma parameters are
+ * for the convenience of port drivers, and for ports where they
+ * aren't meaningful needn't be set to anything special. They can be
+ * altered afterwards by adjusting the relevant members of the parport
+ * structure that is returned and represents the port. They should
+ * not be tampered with after calling parport_announce_port, however.
+ *
+ * If there are parallel port device drivers in the system that have
+ * registered themselves using parport_register_driver(), they are not
+ * told about the port at this time; that is done by
+ * parport_announce_port().
+ *
+ * The @ops structure is allocated by the caller, and must not be
+ * deallocated before calling parport_unregister_port().
+ *
+ * If there is no memory to allocate a new parport structure, this
+ * function will return %NULL.
+ **/
struct parport *parport_register_port(unsigned long base, int irq, int dma,
struct parport_operations *ops)
{
@@ -243,6 +309,17 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
return tmp;
}
+/**
+ * parport_announce_port - tell device drivers about a parallel port
+ * @port: parallel port to announce
+ *
+ * After a port driver has registered a parallel port with
+ * parport_register_port, and performed any necessary initialisation
+ * or adjustments, it should call parport_announce_port() in order to
+ * notify all device drivers that have called
+ * parport_register_driver(). Their attach() functions will be
+ * called, with @port as the parameter.
+ **/
void parport_announce_port (struct parport *port)
{
#ifdef CONFIG_PARPORT_1284
@@ -286,6 +363,23 @@ static void free_port (struct parport *port)
kfree(port);
}
+/**
+ * parport_unregister_port - deregister a parallel port
+ * @port: parallel port to deregister
+ *
+ * When a parallel port driver is forcibly unloaded, or a parallel
+ * port becomes inaccessible, the port driver must call this function
+ * in order to deal with device drivers that still want to use it.
+ *
+ * The parport structure associated with the port has its operations
+ * structure replaced with one containing 'null' operations that
+ * return errors or just don't do anything.
+ *
+ * Any drivers that have registered themselves using
+ * parport_register_driver() are notified that the port is no longer
+ * accessible by having their detach() routines called with @port as
+ * the parameter.
+ **/
void parport_unregister_port(struct parport *port)
{
struct parport *p;
@@ -320,10 +414,76 @@ void parport_unregister_port(struct parport *port)
free_port (port);
}
-struct pardevice *parport_register_device(struct parport *port, const char *name,
- int (*pf)(void *), void (*kf)(void *),
- void (*irq_func)(int, void *, struct pt_regs *),
- int flags, void *handle)
+/**
+ * parport_register_device - register a device on a parallel port
+ * @port: port to which the device is attached
+ * @name: a name to refer to the device
+ * @pf: preemption callback
+ * @kf: kick callback (wake-up)
+ * @irq_func: interrupt handler
+ * @flags: registration flags
+ * @handle: data for callback functions
+ *
+ * This function, called by parallel port device drivers, declares
+ * that a device is connected to a port, and tells the system all it
+ * needs to know.
+ *
+ * The @name is allocated by the caller and must not be deallocated
+ * until the caller calls @parport_unregister_device for that device.
+ *
+ * The preemption callback function, @pf, is called when this device
+ * driver has claimed access to the port but another device driver
+ * wants to use it. It is given @handle as its parameter, and should
+ * return zero if it is willing for the system to release the port to
+ * another driver on its behalf. If it wants to keep control of the
+ * port it should return non-zero, and no action will be taken. It is
+ * good manners for the driver to try to release the port at the
+ * earliest opportunity after its preemption callback rejects a
+ * preemption attempt. Note that if a preemption callback is happy
+ * for preemption to go ahead, there is no need to release the port;
+ * it is done automatically. This function may not block, as it may
+ * be called from interrupt context. If the device driver does not
+ * support preemption, @pf can be %NULL.
+ *
+ * The wake-up ("kick") callback function, @kf, is called when the
+ * port is available to be claimed for exclusive access; that is,
+ * parport_claim() is guaranteed to succeed when called from inside
+ * the wake-up callback function. If the driver wants to claim the
+ * port it should do so; otherwise, it need not take any action. This
+ * function may not block, as it may be called from interrupt context.
+ * If the device driver does not want to be explicitly invited to
+ * claim the port in this way, @kf can be %NULL.
+ *
+ * The interrupt handler, @irq_func, is called when an interrupt
+ * arrives from the parallel port. Note that if a device driver wants
+ * to use interrupts it should use parport_enable_irq(), and can also
+ * check the irq member of the parport structure representing the
+ * port.
+ *
+ * The parallel port (lowlevel) driver is the one that has called
+ * request_irq() and whose interrupt handler is called first. This
+ * handler does whatever needs to be done to the hardware to
+ * acknowledge the interrupt (for PC-style ports there is nothing
+ * special to be done). It then tells the IEEE 1284 code about the
+ * interrupt, which may involve reacting to an IEEE 1284 event
+ * depending on the current IEEE 1284 phase. After this, it calls
+ * @irq_func. Needless to say, @irq_func will be called from
+ * interrupt context, and may not block.
+ *
+ * The %PARPORT_DEV_EXCL flag is for preventing port sharing, and so
+ * should only be used when sharing the port with other device drivers
+ * is impossible and would lead to incorrect behaviour. Use it
+ * sparingly! Normally, @flags will be zero.
+ *
+ * This function returns a pointer to a structure that represents the
+ * device on the port, or %NULL if there is not enough memory to
+ * allocate space for that structure.
+ **/
+struct pardevice *
+parport_register_device(struct parport *port, const char *name,
+ int (*pf)(void *), void (*kf)(void *),
+ void (*irq_func)(int, void *, struct pt_regs *),
+ int flags, void *handle)
{
struct pardevice *tmp;
@@ -341,17 +501,25 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
}
}
+ /* We up our own module reference count, and that of the port
+ on which a device is to be registered, to ensure that
+ neither of us gets unloaded while we sleep in (e.g.)
+ kmalloc. To be absolutely safe, we have to require that
+ our caller doesn't sleep in between parport_enumerate and
+ parport_register_device.. */
+ inc_parport_count();
+ port->ops->inc_use_count();
+
tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL);
if (tmp == NULL) {
printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
- return NULL;
+ goto out;
}
tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL);
if (tmp->state == NULL) {
printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
- kfree(tmp);
- return NULL;
+ goto out_free_pardevice;
}
tmp->name = name;
@@ -376,12 +544,10 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
if (flags & PARPORT_DEV_EXCL) {
if (port->physport->devices) {
spin_unlock (&port->physport->pardevice_lock);
- kfree (tmp->state);
- kfree (tmp);
printk (KERN_DEBUG
"%s: cannot grant exclusive access for "
"device %s\n", port->name, name);
- return NULL;
+ goto out_free_all;
}
port->flags |= PARPORT_FLAG_EXCL;
}
@@ -392,9 +558,6 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
port->physport->devices = tmp;
spin_unlock(&port->physport->pardevice_lock);
- inc_parport_count();
- port->ops->inc_use_count();
-
init_waitqueue_head(&tmp->wait_q);
tmp->timeslice = parport_default_timeslice;
tmp->waitnext = tmp->waitprev = NULL;
@@ -406,8 +569,23 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
port->ops->init_state(tmp, tmp->state);
parport_device_proc_register(tmp);
return tmp;
+
+ out_free_all:
+ kfree (tmp->state);
+ out_free_pardevice:
+ kfree (tmp);
+ out:
+ dec_parport_count();
+ port->ops->dec_use_count();
+ return NULL;
}
+/**
+ * parport_unregister_device - deregister a device on a parallel port
+ * @dev: pointer to structure representing device
+ *
+ * This undoes the effect of parport_register_device().
+ **/
void parport_unregister_device(struct pardevice *dev)
{
struct parport *port;
@@ -454,6 +632,16 @@ void parport_unregister_device(struct pardevice *dev)
free_port (port);
}
+/**
+ * parport_claim - claim access to a parallel port device
+ * @dev: pointer to structure representing a device on the port
+ *
+ * This function will not block and so can be used from interrupt
+ * context. If parport_claim() succeeds in claiming access to the
+ * port it returns zero and the port is available to use. It may fail
+ * (returning non-zero) if the port is in use by another driver and
+ * that driver is not willing to relinquish control of the port.
+ **/
int parport_claim(struct pardevice *dev)
{
struct pardevice *oldcad;
@@ -555,6 +743,15 @@ blocked:
return -EAGAIN;
}
+/**
+ * parport_claim_or_block - claim access to a parallel port device
+ * @dev: pointer to structure representing a device on the port
+ *
+ * This behaves like parport_claim(), but will block if necessary to
+ * wait for the port to be free. A return value of 1 indicates that
+ * it slept; 0 means that it succeeded without needing to sleep. A
+ * negative error code indicates failure.
+ **/
int parport_claim_or_block(struct pardevice *dev)
{
int r;
@@ -597,6 +794,14 @@ int parport_claim_or_block(struct pardevice *dev)
return r;
}
+/**
+ * parport_release - give up access to a parallel port device
+ * @dev: pointer to structure representing parallel port device
+ *
+ * This function cannot fail, but it should not be called without the
+ * port claimed. Similarly, if the port is already claimed you should
+ * not try claiming it again.
+ **/
void parport_release(struct pardevice *dev)
{
struct parport *port = dev->port->physport;