/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
* Parallel-port resource manager code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
* Tim Waugh <tim@cyberelk.demon.co.uk>
* Jose Renau <renau@acm.org>
* Philip Blundell <philb@gnu.org>
* Andrea Arcangeli
*
* based on work by Grant Guenther <grant@torque.net>
* and Philip Blundell
*
* Any part of this program may be used in documents licensed under
* the GNU Free Documentation License, Version 1.1 or any later version
* published by the Free Software Foundation.
*/
#undef PARPORT_DEBUG_SHARING /* undef for production */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/threads.h>
#include <linux/parport.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/kmod.h>
#include <linux/spinlock.h>
#include <asm/irq.h>
#undef PARPORT_PARANOID
#define PARPORT_DEFAULT_TIMESLICE (HZ/5)
unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
int parport_default_spintime = DEFAULT_SPIN_TIME;
static LIST_HEAD(portlist);
static DEFINE_SPINLOCK(parportlist_lock);
/* list of all allocated ports, sorted by ->number */
static LIST_HEAD(all_ports);
static DEFINE_SPINLOCK(full_list_lock);
static LIST_HEAD(drivers);
static DECLARE_MUTEX(registration_lock);
/* What you can do to a port that's gone away.. */
static void dead_write_lines (struct parport *p, unsigned char b){}
static unsigned char dead_read_lines (struct parport *p) { return 0; }
static unsigned char dead_frob_lines (struct parport *p, unsigned char b,
unsigned char c) { return 0; }
static void dead_onearg (struct parport *p){}
static void dead_initstate (struct pardevice *d, struct parport_state *s) { }
static void dead_state (struct parport *p, struct parport_state *s) { }
static size_t dead_write (struct parport *p, const void *b, size_t l, int f)
{ return 0; }
static size_t dead_read (struct parport *p, void *b, size_t l, int f)
{ return 0; }
static struct parport_operations dead_ops = {
.write_data = dead_write_lines, /* data */
.read_data = dead_read_lines,
.write_control = dead_write_lines, /* control */
.read_control = dead_read_lines,
.frob_control = dead_frob_lines,
.read_status = dead_read_lines, /* status */
.enable_irq = dead_onearg, /* enable_irq */
.disable_irq = dead_onearg, /* disable_irq */
.data_forward = dead_onearg, /* data_forward */
.data_reverse = dead_onearg, /* data_reverse */
.init_state = dead_initstate, /* init_state */
.save_state = dead_state,
.restore_state = dead_state,
.epp_write_data = dead_write, /* epp */
.epp_read_data = dead_read,
.epp_write_addr = dead_write,
.epp_read_addr = dead_read,
.ecp_write_data = dead_write, /* ecp */
.ecp_read_data = dead_read,
.ecp_write_addr = dead_write,
.compat_write_data = dead_write, /* compat */
.nibble_read_data = dead_read, /* nibble */
.byte_read_data = dead_read, /* byte */
.owner = NULL,
};
/* Call attach(port) for each registered driver. */
static void attach_driver_chain(struct parport *port)
{
/* caller has exclusive registration_lock */
struct parport_driver *drv;
list_for_each_entry(drv, &drivers, list)
drv->attach(port);
}
/* Call detach(port) for each registered driver. */
static void detach_driver_chain(struct parport *port)
{
struct parport_driver *drv;
/* caller has exclusive registration_lock */
list_for_each_entry(drv, &drivers, list)
drv->detach (port);
}
/* Ask kmod for some lowlevel drivers. */
static void get_lowlevel_driver (void)
{
/* There is no actual module called this: you should set
* up an alias for modutils. */
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().
*
* The driver's attach() function may block. The port that
* attach() is given will be valid for the duration of the
* callback, but if the driver wants to take a copy of the
* pointer it must call parport_get_port() to do so. Calling
* parport_register_device() on that port will do this for you.
*
* The driver's detach() function may block. The port that
* detach() is given will be valid for the duration of the
* callback, but if the driver wants to take a copy of the
* pointer it must call parport_get_port() to do so.
*
* Returns 0 on success. Currently it always succeeds.
**/
int parport_register_driver (struct parport_driver *drv)
{
struct parport *port;
if (list_empty(&portlist))
get_lowlevel_driver ();
down