18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Parallel-port resource manager code.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
58c2ecf20Sopenharmony_ci *          Tim Waugh <tim@cyberelk.demon.co.uk>
68c2ecf20Sopenharmony_ci *          Jose Renau <renau@acm.org>
78c2ecf20Sopenharmony_ci *          Philip Blundell <philb@gnu.org>
88c2ecf20Sopenharmony_ci *	    Andrea Arcangeli
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * based on work by Grant Guenther <grant@torque.net>
118c2ecf20Sopenharmony_ci *          and Philip Blundell
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Any part of this program may be used in documents licensed under
148c2ecf20Sopenharmony_ci * the GNU Free Documentation License, Version 1.1 or any later version
158c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#undef PARPORT_DEBUG_SHARING		/* undef for production */
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <linux/module.h>
218c2ecf20Sopenharmony_ci#include <linux/string.h>
228c2ecf20Sopenharmony_ci#include <linux/threads.h>
238c2ecf20Sopenharmony_ci#include <linux/parport.h>
248c2ecf20Sopenharmony_ci#include <linux/delay.h>
258c2ecf20Sopenharmony_ci#include <linux/errno.h>
268c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
278c2ecf20Sopenharmony_ci#include <linux/ioport.h>
288c2ecf20Sopenharmony_ci#include <linux/kernel.h>
298c2ecf20Sopenharmony_ci#include <linux/slab.h>
308c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
318c2ecf20Sopenharmony_ci#include <linux/kmod.h>
328c2ecf20Sopenharmony_ci#include <linux/device.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
358c2ecf20Sopenharmony_ci#include <linux/mutex.h>
368c2ecf20Sopenharmony_ci#include <asm/irq.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#undef PARPORT_PARANOID
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define PARPORT_DEFAULT_TIMESLICE	(HZ/5)
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciunsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
438c2ecf20Sopenharmony_ciint parport_default_spintime =  DEFAULT_SPIN_TIME;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic LIST_HEAD(portlist);
468c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(parportlist_lock);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* list of all allocated ports, sorted by ->number */
498c2ecf20Sopenharmony_cistatic LIST_HEAD(all_ports);
508c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(full_list_lock);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic LIST_HEAD(drivers);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(registration_lock);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* What you can do to a port that's gone away.. */
578c2ecf20Sopenharmony_cistatic void dead_write_lines(struct parport *p, unsigned char b){}
588c2ecf20Sopenharmony_cistatic unsigned char dead_read_lines(struct parport *p) { return 0; }
598c2ecf20Sopenharmony_cistatic unsigned char dead_frob_lines(struct parport *p, unsigned char b,
608c2ecf20Sopenharmony_ci			     unsigned char c) { return 0; }
618c2ecf20Sopenharmony_cistatic void dead_onearg(struct parport *p){}
628c2ecf20Sopenharmony_cistatic void dead_initstate(struct pardevice *d, struct parport_state *s) { }
638c2ecf20Sopenharmony_cistatic void dead_state(struct parport *p, struct parport_state *s) { }
648c2ecf20Sopenharmony_cistatic size_t dead_write(struct parport *p, const void *b, size_t l, int f)
658c2ecf20Sopenharmony_ci{ return 0; }
668c2ecf20Sopenharmony_cistatic size_t dead_read(struct parport *p, void *b, size_t l, int f)
678c2ecf20Sopenharmony_ci{ return 0; }
688c2ecf20Sopenharmony_cistatic struct parport_operations dead_ops = {
698c2ecf20Sopenharmony_ci	.write_data	= dead_write_lines,	/* data */
708c2ecf20Sopenharmony_ci	.read_data	= dead_read_lines,
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	.write_control	= dead_write_lines,	/* control */
738c2ecf20Sopenharmony_ci	.read_control	= dead_read_lines,
748c2ecf20Sopenharmony_ci	.frob_control	= dead_frob_lines,
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	.read_status	= dead_read_lines,	/* status */
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	.enable_irq	= dead_onearg,		/* enable_irq */
798c2ecf20Sopenharmony_ci	.disable_irq	= dead_onearg,		/* disable_irq */
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	.data_forward	= dead_onearg,		/* data_forward */
828c2ecf20Sopenharmony_ci	.data_reverse	= dead_onearg,		/* data_reverse */
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	.init_state	= dead_initstate,	/* init_state */
858c2ecf20Sopenharmony_ci	.save_state	= dead_state,
868c2ecf20Sopenharmony_ci	.restore_state	= dead_state,
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	.epp_write_data	= dead_write,		/* epp */
898c2ecf20Sopenharmony_ci	.epp_read_data	= dead_read,
908c2ecf20Sopenharmony_ci	.epp_write_addr	= dead_write,
918c2ecf20Sopenharmony_ci	.epp_read_addr	= dead_read,
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	.ecp_write_data	= dead_write,		/* ecp */
948c2ecf20Sopenharmony_ci	.ecp_read_data	= dead_read,
958c2ecf20Sopenharmony_ci	.ecp_write_addr	= dead_write,
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	.compat_write_data	= dead_write,	/* compat */
988c2ecf20Sopenharmony_ci	.nibble_read_data	= dead_read,	/* nibble */
998c2ecf20Sopenharmony_ci	.byte_read_data		= dead_read,	/* byte */
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	.owner		= NULL,
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic struct device_type parport_device_type = {
1058c2ecf20Sopenharmony_ci	.name = "parport",
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic int is_parport(struct device *dev)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	return dev->type == &parport_device_type;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic int parport_probe(struct device *dev)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	struct parport_driver *drv;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	if (is_parport(dev))
1188c2ecf20Sopenharmony_ci		return -ENODEV;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	drv = to_parport_driver(dev->driver);
1218c2ecf20Sopenharmony_ci	if (!drv->probe) {
1228c2ecf20Sopenharmony_ci		/* if driver has not defined a custom probe */
1238c2ecf20Sopenharmony_ci		struct pardevice *par_dev = to_pardevice(dev);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci		if (strcmp(par_dev->name, drv->name))
1268c2ecf20Sopenharmony_ci			return -ENODEV;
1278c2ecf20Sopenharmony_ci		return 0;
1288c2ecf20Sopenharmony_ci	}
1298c2ecf20Sopenharmony_ci	/* if driver defined its own probe */
1308c2ecf20Sopenharmony_ci	return drv->probe(to_pardevice(dev));
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic struct bus_type parport_bus_type = {
1348c2ecf20Sopenharmony_ci	.name = "parport",
1358c2ecf20Sopenharmony_ci	.probe = parport_probe,
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ciint parport_bus_init(void)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	return bus_register(&parport_bus_type);
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_civoid parport_bus_exit(void)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	bus_unregister(&parport_bus_type);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/*
1498c2ecf20Sopenharmony_ci * iterates through all the drivers registered with the bus and sends the port
1508c2ecf20Sopenharmony_ci * details to the match_port callback of the driver, so that the driver can
1518c2ecf20Sopenharmony_ci * know about the new port that just registered with the bus and decide if it
1528c2ecf20Sopenharmony_ci * wants to use this new port.
1538c2ecf20Sopenharmony_ci */
1548c2ecf20Sopenharmony_cistatic int driver_check(struct device_driver *dev_drv, void *_port)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct parport *port = _port;
1578c2ecf20Sopenharmony_ci	struct parport_driver *drv = to_parport_driver(dev_drv);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	if (drv->match_port)
1608c2ecf20Sopenharmony_ci		drv->match_port(port);
1618c2ecf20Sopenharmony_ci	return 0;
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/* Call attach(port) for each registered driver. */
1658c2ecf20Sopenharmony_cistatic void attach_driver_chain(struct parport *port)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	/* caller has exclusive registration_lock */
1688c2ecf20Sopenharmony_ci	struct parport_driver *drv;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	list_for_each_entry(drv, &drivers, list)
1718c2ecf20Sopenharmony_ci		drv->attach(port);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	/*
1748c2ecf20Sopenharmony_ci	 * call the driver_check function of the drivers registered in
1758c2ecf20Sopenharmony_ci	 * new device model
1768c2ecf20Sopenharmony_ci	 */
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	bus_for_each_drv(&parport_bus_type, NULL, port, driver_check);
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic int driver_detach(struct device_driver *_drv, void *_port)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	struct parport *port = _port;
1848c2ecf20Sopenharmony_ci	struct parport_driver *drv = to_parport_driver(_drv);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (drv->detach)
1878c2ecf20Sopenharmony_ci		drv->detach(port);
1888c2ecf20Sopenharmony_ci	return 0;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/* Call detach(port) for each registered driver. */
1928c2ecf20Sopenharmony_cistatic void detach_driver_chain(struct parport *port)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct parport_driver *drv;
1958c2ecf20Sopenharmony_ci	/* caller has exclusive registration_lock */
1968c2ecf20Sopenharmony_ci	list_for_each_entry(drv, &drivers, list)
1978c2ecf20Sopenharmony_ci		drv->detach(port);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/*
2008c2ecf20Sopenharmony_ci	 * call the detach function of the drivers registered in
2018c2ecf20Sopenharmony_ci	 * new device model
2028c2ecf20Sopenharmony_ci	 */
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	bus_for_each_drv(&parport_bus_type, NULL, port, driver_detach);
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci/* Ask kmod for some lowlevel drivers. */
2088c2ecf20Sopenharmony_cistatic void get_lowlevel_driver(void)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	/*
2118c2ecf20Sopenharmony_ci	 * There is no actual module called this: you should set
2128c2ecf20Sopenharmony_ci	 * up an alias for modutils.
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci	request_module("parport_lowlevel");
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci/*
2188c2ecf20Sopenharmony_ci * iterates through all the devices connected to the bus and sends the device
2198c2ecf20Sopenharmony_ci * details to the match_port callback of the driver, so that the driver can
2208c2ecf20Sopenharmony_ci * know what are all the ports that are connected to the bus and choose the
2218c2ecf20Sopenharmony_ci * port to which it wants to register its device.
2228c2ecf20Sopenharmony_ci */
2238c2ecf20Sopenharmony_cistatic int port_check(struct device *dev, void *dev_drv)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	struct parport_driver *drv = dev_drv;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	/* only send ports, do not send other devices connected to bus */
2288c2ecf20Sopenharmony_ci	if (is_parport(dev))
2298c2ecf20Sopenharmony_ci		drv->match_port(to_parport_dev(dev));
2308c2ecf20Sopenharmony_ci	return 0;
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/*
2348c2ecf20Sopenharmony_ci * Iterates through all the devices connected to the bus and return 1
2358c2ecf20Sopenharmony_ci * if the device is a parallel port.
2368c2ecf20Sopenharmony_ci */
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic int port_detect(struct device *dev, void *dev_drv)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	if (is_parport(dev))
2418c2ecf20Sopenharmony_ci		return 1;
2428c2ecf20Sopenharmony_ci	return 0;
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci/**
2468c2ecf20Sopenharmony_ci *	parport_register_driver - register a parallel port device driver
2478c2ecf20Sopenharmony_ci *	@drv: structure describing the driver
2488c2ecf20Sopenharmony_ci *	@owner: owner module of drv
2498c2ecf20Sopenharmony_ci *	@mod_name: module name string
2508c2ecf20Sopenharmony_ci *
2518c2ecf20Sopenharmony_ci *	This can be called by a parallel port device driver in order
2528c2ecf20Sopenharmony_ci *	to receive notifications about ports being found in the
2538c2ecf20Sopenharmony_ci *	system, as well as ports no longer available.
2548c2ecf20Sopenharmony_ci *
2558c2ecf20Sopenharmony_ci *	If devmodel is true then the new device model is used
2568c2ecf20Sopenharmony_ci *	for registration.
2578c2ecf20Sopenharmony_ci *
2588c2ecf20Sopenharmony_ci *	The @drv structure is allocated by the caller and must not be
2598c2ecf20Sopenharmony_ci *	deallocated until after calling parport_unregister_driver().
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci *	If using the non device model:
2628c2ecf20Sopenharmony_ci *	The driver's attach() function may block.  The port that
2638c2ecf20Sopenharmony_ci *	attach() is given will be valid for the duration of the
2648c2ecf20Sopenharmony_ci *	callback, but if the driver wants to take a copy of the
2658c2ecf20Sopenharmony_ci *	pointer it must call parport_get_port() to do so.  Calling
2668c2ecf20Sopenharmony_ci *	parport_register_device() on that port will do this for you.
2678c2ecf20Sopenharmony_ci *
2688c2ecf20Sopenharmony_ci *	The driver's detach() function may block.  The port that
2698c2ecf20Sopenharmony_ci *	detach() is given will be valid for the duration of the
2708c2ecf20Sopenharmony_ci *	callback, but if the driver wants to take a copy of the
2718c2ecf20Sopenharmony_ci *	pointer it must call parport_get_port() to do so.
2728c2ecf20Sopenharmony_ci *
2738c2ecf20Sopenharmony_ci *
2748c2ecf20Sopenharmony_ci *	Returns 0 on success. The non device model will always succeeds.
2758c2ecf20Sopenharmony_ci *	but the new device model can fail and will return the error code.
2768c2ecf20Sopenharmony_ci **/
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ciint __parport_register_driver(struct parport_driver *drv, struct module *owner,
2798c2ecf20Sopenharmony_ci			      const char *mod_name)
2808c2ecf20Sopenharmony_ci{
2818c2ecf20Sopenharmony_ci	/* using device model */
2828c2ecf20Sopenharmony_ci	int ret;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* initialize common driver fields */
2858c2ecf20Sopenharmony_ci	drv->driver.name = drv->name;
2868c2ecf20Sopenharmony_ci	drv->driver.bus = &parport_bus_type;
2878c2ecf20Sopenharmony_ci	drv->driver.owner = owner;
2888c2ecf20Sopenharmony_ci	drv->driver.mod_name = mod_name;
2898c2ecf20Sopenharmony_ci	ret = driver_register(&drv->driver);
2908c2ecf20Sopenharmony_ci	if (ret)
2918c2ecf20Sopenharmony_ci		return ret;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/*
2948c2ecf20Sopenharmony_ci	 * check if bus has any parallel port registered, if
2958c2ecf20Sopenharmony_ci	 * none is found then load the lowlevel driver.
2968c2ecf20Sopenharmony_ci	 */
2978c2ecf20Sopenharmony_ci	ret = bus_for_each_dev(&parport_bus_type, NULL, NULL,
2988c2ecf20Sopenharmony_ci			       port_detect);
2998c2ecf20Sopenharmony_ci	if (!ret)
3008c2ecf20Sopenharmony_ci		get_lowlevel_driver();
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	mutex_lock(&registration_lock);
3038c2ecf20Sopenharmony_ci	if (drv->match_port)
3048c2ecf20Sopenharmony_ci		bus_for_each_dev(&parport_bus_type, NULL, drv,
3058c2ecf20Sopenharmony_ci				 port_check);
3068c2ecf20Sopenharmony_ci	mutex_unlock(&registration_lock);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	return 0;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__parport_register_driver);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic int port_detach(struct device *dev, void *_drv)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	struct parport_driver *drv = _drv;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (is_parport(dev) && drv->detach)
3178c2ecf20Sopenharmony_ci		drv->detach(to_parport_dev(dev));
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	return 0;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci/**
3238c2ecf20Sopenharmony_ci *	parport_unregister_driver - deregister a parallel port device driver
3248c2ecf20Sopenharmony_ci *	@drv: structure describing the driver that was given to
3258c2ecf20Sopenharmony_ci *	      parport_register_driver()
3268c2ecf20Sopenharmony_ci *
3278c2ecf20Sopenharmony_ci *	This should be called by a parallel port device driver that
3288c2ecf20Sopenharmony_ci *	has registered itself using parport_register_driver() when it
3298c2ecf20Sopenharmony_ci *	is about to be unloaded.
3308c2ecf20Sopenharmony_ci *
3318c2ecf20Sopenharmony_ci *	When it returns, the driver's attach() routine will no longer
3328c2ecf20Sopenharmony_ci *	be called, and for each port that attach() was called for, the
3338c2ecf20Sopenharmony_ci *	detach() routine will have been called.
3348c2ecf20Sopenharmony_ci *
3358c2ecf20Sopenharmony_ci *	All the driver's attach() and detach() calls are guaranteed to have
3368c2ecf20Sopenharmony_ci *	finished by the time this function returns.
3378c2ecf20Sopenharmony_ci **/
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_civoid parport_unregister_driver(struct parport_driver *drv)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	mutex_lock(&registration_lock);
3428c2ecf20Sopenharmony_ci	bus_for_each_dev(&parport_bus_type, NULL, drv, port_detach);
3438c2ecf20Sopenharmony_ci	driver_unregister(&drv->driver);
3448c2ecf20Sopenharmony_ci	mutex_unlock(&registration_lock);
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_unregister_driver);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cistatic void free_port(struct device *dev)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	int d;
3518c2ecf20Sopenharmony_ci	struct parport *port = to_parport_dev(dev);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	spin_lock(&full_list_lock);
3548c2ecf20Sopenharmony_ci	list_del(&port->full_list);
3558c2ecf20Sopenharmony_ci	spin_unlock(&full_list_lock);
3568c2ecf20Sopenharmony_ci	for (d = 0; d < 5; d++) {
3578c2ecf20Sopenharmony_ci		kfree(port->probe_info[d].class_name);
3588c2ecf20Sopenharmony_ci		kfree(port->probe_info[d].mfr);
3598c2ecf20Sopenharmony_ci		kfree(port->probe_info[d].model);
3608c2ecf20Sopenharmony_ci		kfree(port->probe_info[d].cmdset);
3618c2ecf20Sopenharmony_ci		kfree(port->probe_info[d].description);
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	kfree(port->name);
3658c2ecf20Sopenharmony_ci	kfree(port);
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci/**
3698c2ecf20Sopenharmony_ci *	parport_get_port - increment a port's reference count
3708c2ecf20Sopenharmony_ci *	@port: the port
3718c2ecf20Sopenharmony_ci *
3728c2ecf20Sopenharmony_ci *	This ensures that a struct parport pointer remains valid
3738c2ecf20Sopenharmony_ci *	until the matching parport_put_port() call.
3748c2ecf20Sopenharmony_ci **/
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_cistruct parport *parport_get_port(struct parport *port)
3778c2ecf20Sopenharmony_ci{
3788c2ecf20Sopenharmony_ci	struct device *dev = get_device(&port->bus_dev);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	return to_parport_dev(dev);
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_get_port);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_civoid parport_del_port(struct parport *port)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	device_unregister(&port->bus_dev);
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_del_port);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci/**
3918c2ecf20Sopenharmony_ci *	parport_put_port - decrement a port's reference count
3928c2ecf20Sopenharmony_ci *	@port: the port
3938c2ecf20Sopenharmony_ci *
3948c2ecf20Sopenharmony_ci *	This should be called once for each call to parport_get_port(),
3958c2ecf20Sopenharmony_ci *	once the port is no longer needed. When the reference count reaches
3968c2ecf20Sopenharmony_ci *	zero (port is no longer used), free_port is called.
3978c2ecf20Sopenharmony_ci **/
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_civoid parport_put_port(struct parport *port)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	put_device(&port->bus_dev);
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_put_port);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci/**
4068c2ecf20Sopenharmony_ci *	parport_register_port - register a parallel port
4078c2ecf20Sopenharmony_ci *	@base: base I/O address
4088c2ecf20Sopenharmony_ci *	@irq: IRQ line
4098c2ecf20Sopenharmony_ci *	@dma: DMA channel
4108c2ecf20Sopenharmony_ci *	@ops: pointer to the port driver's port operations structure
4118c2ecf20Sopenharmony_ci *
4128c2ecf20Sopenharmony_ci *	When a parallel port (lowlevel) driver finds a port that
4138c2ecf20Sopenharmony_ci *	should be made available to parallel port device drivers, it
4148c2ecf20Sopenharmony_ci *	should call parport_register_port().  The @base, @irq, and
4158c2ecf20Sopenharmony_ci *	@dma parameters are for the convenience of port drivers, and
4168c2ecf20Sopenharmony_ci *	for ports where they aren't meaningful needn't be set to
4178c2ecf20Sopenharmony_ci *	anything special.  They can be altered afterwards by adjusting
4188c2ecf20Sopenharmony_ci *	the relevant members of the parport structure that is returned
4198c2ecf20Sopenharmony_ci *	and represents the port.  They should not be tampered with
4208c2ecf20Sopenharmony_ci *	after calling parport_announce_port, however.
4218c2ecf20Sopenharmony_ci *
4228c2ecf20Sopenharmony_ci *	If there are parallel port device drivers in the system that
4238c2ecf20Sopenharmony_ci *	have registered themselves using parport_register_driver(),
4248c2ecf20Sopenharmony_ci *	they are not told about the port at this time; that is done by
4258c2ecf20Sopenharmony_ci *	parport_announce_port().
4268c2ecf20Sopenharmony_ci *
4278c2ecf20Sopenharmony_ci *	The @ops structure is allocated by the caller, and must not be
4288c2ecf20Sopenharmony_ci *	deallocated before calling parport_remove_port().
4298c2ecf20Sopenharmony_ci *
4308c2ecf20Sopenharmony_ci *	If there is no memory to allocate a new parport structure,
4318c2ecf20Sopenharmony_ci *	this function will return %NULL.
4328c2ecf20Sopenharmony_ci **/
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_cistruct parport *parport_register_port(unsigned long base, int irq, int dma,
4358c2ecf20Sopenharmony_ci				      struct parport_operations *ops)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	struct list_head *l;
4388c2ecf20Sopenharmony_ci	struct parport *tmp;
4398c2ecf20Sopenharmony_ci	int num;
4408c2ecf20Sopenharmony_ci	int device;
4418c2ecf20Sopenharmony_ci	char *name;
4428c2ecf20Sopenharmony_ci	int ret;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	tmp = kzalloc(sizeof(struct parport), GFP_KERNEL);
4458c2ecf20Sopenharmony_ci	if (!tmp)
4468c2ecf20Sopenharmony_ci		return NULL;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	/* Init our structure */
4498c2ecf20Sopenharmony_ci	tmp->base = base;
4508c2ecf20Sopenharmony_ci	tmp->irq = irq;
4518c2ecf20Sopenharmony_ci	tmp->dma = dma;
4528c2ecf20Sopenharmony_ci	tmp->muxport = tmp->daisy = tmp->muxsel = -1;
4538c2ecf20Sopenharmony_ci	tmp->modes = 0;
4548c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&tmp->list);
4558c2ecf20Sopenharmony_ci	tmp->devices = tmp->cad = NULL;
4568c2ecf20Sopenharmony_ci	tmp->flags = 0;
4578c2ecf20Sopenharmony_ci	tmp->ops = ops;
4588c2ecf20Sopenharmony_ci	tmp->physport = tmp;
4598c2ecf20Sopenharmony_ci	memset(tmp->probe_info, 0, 5 * sizeof(struct parport_device_info));
4608c2ecf20Sopenharmony_ci	rwlock_init(&tmp->cad_lock);
4618c2ecf20Sopenharmony_ci	spin_lock_init(&tmp->waitlist_lock);
4628c2ecf20Sopenharmony_ci	spin_lock_init(&tmp->pardevice_lock);
4638c2ecf20Sopenharmony_ci	tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
4648c2ecf20Sopenharmony_ci	tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
4658c2ecf20Sopenharmony_ci	sema_init(&tmp->ieee1284.irq, 0);
4668c2ecf20Sopenharmony_ci	tmp->spintime = parport_default_spintime;
4678c2ecf20Sopenharmony_ci	atomic_set(&tmp->ref_count, 1);
4688c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&tmp->full_list);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	name = kmalloc(15, GFP_KERNEL);
4718c2ecf20Sopenharmony_ci	if (!name) {
4728c2ecf20Sopenharmony_ci		kfree(tmp);
4738c2ecf20Sopenharmony_ci		return NULL;
4748c2ecf20Sopenharmony_ci	}
4758c2ecf20Sopenharmony_ci	/* Search for the lowest free parport number. */
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	spin_lock(&full_list_lock);
4788c2ecf20Sopenharmony_ci	for (l = all_ports.next, num = 0; l != &all_ports; l = l->next, num++) {
4798c2ecf20Sopenharmony_ci		struct parport *p = list_entry(l, struct parport, full_list);
4808c2ecf20Sopenharmony_ci		if (p->number != num)
4818c2ecf20Sopenharmony_ci			break;
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci	tmp->portnum = tmp->number = num;
4848c2ecf20Sopenharmony_ci	list_add_tail(&tmp->full_list, l);
4858c2ecf20Sopenharmony_ci	spin_unlock(&full_list_lock);
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	/*
4888c2ecf20Sopenharmony_ci	 * Now that the portnum is known finish doing the Init.
4898c2ecf20Sopenharmony_ci	 */
4908c2ecf20Sopenharmony_ci	sprintf(name, "parport%d", tmp->portnum = tmp->number);
4918c2ecf20Sopenharmony_ci	tmp->name = name;
4928c2ecf20Sopenharmony_ci	tmp->bus_dev.bus = &parport_bus_type;
4938c2ecf20Sopenharmony_ci	tmp->bus_dev.release = free_port;
4948c2ecf20Sopenharmony_ci	dev_set_name(&tmp->bus_dev, name);
4958c2ecf20Sopenharmony_ci	tmp->bus_dev.type = &parport_device_type;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	for (device = 0; device < 5; device++)
4988c2ecf20Sopenharmony_ci		/* assume the worst */
4998c2ecf20Sopenharmony_ci		tmp->probe_info[device].class = PARPORT_CLASS_LEGACY;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	tmp->waithead = tmp->waittail = NULL;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	ret = device_register(&tmp->bus_dev);
5048c2ecf20Sopenharmony_ci	if (ret) {
5058c2ecf20Sopenharmony_ci		put_device(&tmp->bus_dev);
5068c2ecf20Sopenharmony_ci		return NULL;
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	return tmp;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_register_port);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci/**
5148c2ecf20Sopenharmony_ci *	parport_announce_port - tell device drivers about a parallel port
5158c2ecf20Sopenharmony_ci *	@port: parallel port to announce
5168c2ecf20Sopenharmony_ci *
5178c2ecf20Sopenharmony_ci *	After a port driver has registered a parallel port with
5188c2ecf20Sopenharmony_ci *	parport_register_port, and performed any necessary
5198c2ecf20Sopenharmony_ci *	initialisation or adjustments, it should call
5208c2ecf20Sopenharmony_ci *	parport_announce_port() in order to notify all device drivers
5218c2ecf20Sopenharmony_ci *	that have called parport_register_driver().  Their attach()
5228c2ecf20Sopenharmony_ci *	functions will be called, with @port as the parameter.
5238c2ecf20Sopenharmony_ci **/
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_civoid parport_announce_port(struct parport *port)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	int i;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci#ifdef CONFIG_PARPORT_1284
5308c2ecf20Sopenharmony_ci	/* Analyse the IEEE1284.3 topology of the port. */
5318c2ecf20Sopenharmony_ci	parport_daisy_init(port);
5328c2ecf20Sopenharmony_ci#endif
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	if (!port->dev)
5358c2ecf20Sopenharmony_ci		pr_warn("%s: fix this legacy no-device port driver!\n",
5368c2ecf20Sopenharmony_ci			port->name);
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	parport_proc_register(port);
5398c2ecf20Sopenharmony_ci	mutex_lock(&registration_lock);
5408c2ecf20Sopenharmony_ci	spin_lock_irq(&parportlist_lock);
5418c2ecf20Sopenharmony_ci	list_add_tail(&port->list, &portlist);
5428c2ecf20Sopenharmony_ci	for (i = 1; i < 3; i++) {
5438c2ecf20Sopenharmony_ci		struct parport *slave = port->slaves[i-1];
5448c2ecf20Sopenharmony_ci		if (slave)
5458c2ecf20Sopenharmony_ci			list_add_tail(&slave->list, &portlist);
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci	spin_unlock_irq(&parportlist_lock);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* Let drivers know that new port(s) has arrived. */
5508c2ecf20Sopenharmony_ci	attach_driver_chain(port);
5518c2ecf20Sopenharmony_ci	for (i = 1; i < 3; i++) {
5528c2ecf20Sopenharmony_ci		struct parport *slave = port->slaves[i-1];
5538c2ecf20Sopenharmony_ci		if (slave)
5548c2ecf20Sopenharmony_ci			attach_driver_chain(slave);
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci	mutex_unlock(&registration_lock);
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_announce_port);
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/**
5618c2ecf20Sopenharmony_ci *	parport_remove_port - deregister a parallel port
5628c2ecf20Sopenharmony_ci *	@port: parallel port to deregister
5638c2ecf20Sopenharmony_ci *
5648c2ecf20Sopenharmony_ci *	When a parallel port driver is forcibly unloaded, or a
5658c2ecf20Sopenharmony_ci *	parallel port becomes inaccessible, the port driver must call
5668c2ecf20Sopenharmony_ci *	this function in order to deal with device drivers that still
5678c2ecf20Sopenharmony_ci *	want to use it.
5688c2ecf20Sopenharmony_ci *
5698c2ecf20Sopenharmony_ci *	The parport structure associated with the port has its
5708c2ecf20Sopenharmony_ci *	operations structure replaced with one containing 'null'
5718c2ecf20Sopenharmony_ci *	operations that return errors or just don't do anything.
5728c2ecf20Sopenharmony_ci *
5738c2ecf20Sopenharmony_ci *	Any drivers that have registered themselves using
5748c2ecf20Sopenharmony_ci *	parport_register_driver() are notified that the port is no
5758c2ecf20Sopenharmony_ci *	longer accessible by having their detach() routines called
5768c2ecf20Sopenharmony_ci *	with @port as the parameter.
5778c2ecf20Sopenharmony_ci **/
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_civoid parport_remove_port(struct parport *port)
5808c2ecf20Sopenharmony_ci{
5818c2ecf20Sopenharmony_ci	int i;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	mutex_lock(&registration_lock);
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	/* Spread the word. */
5868c2ecf20Sopenharmony_ci	detach_driver_chain(port);
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci#ifdef CONFIG_PARPORT_1284
5898c2ecf20Sopenharmony_ci	/* Forget the IEEE1284.3 topology of the port. */
5908c2ecf20Sopenharmony_ci	parport_daisy_fini(port);
5918c2ecf20Sopenharmony_ci	for (i = 1; i < 3; i++) {
5928c2ecf20Sopenharmony_ci		struct parport *slave = port->slaves[i-1];
5938c2ecf20Sopenharmony_ci		if (!slave)
5948c2ecf20Sopenharmony_ci			continue;
5958c2ecf20Sopenharmony_ci		detach_driver_chain(slave);
5968c2ecf20Sopenharmony_ci		parport_daisy_fini(slave);
5978c2ecf20Sopenharmony_ci	}
5988c2ecf20Sopenharmony_ci#endif
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	port->ops = &dead_ops;
6018c2ecf20Sopenharmony_ci	spin_lock(&parportlist_lock);
6028c2ecf20Sopenharmony_ci	list_del_init(&port->list);
6038c2ecf20Sopenharmony_ci	for (i = 1; i < 3; i++) {
6048c2ecf20Sopenharmony_ci		struct parport *slave = port->slaves[i-1];
6058c2ecf20Sopenharmony_ci		if (slave)
6068c2ecf20Sopenharmony_ci			list_del_init(&slave->list);
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci	spin_unlock(&parportlist_lock);
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	mutex_unlock(&registration_lock);
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	parport_proc_unregister(port);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	for (i = 1; i < 3; i++) {
6158c2ecf20Sopenharmony_ci		struct parport *slave = port->slaves[i-1];
6168c2ecf20Sopenharmony_ci		if (slave)
6178c2ecf20Sopenharmony_ci			parport_put_port(slave);
6188c2ecf20Sopenharmony_ci	}
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_remove_port);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic void free_pardevice(struct device *dev)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	struct pardevice *par_dev = to_pardevice(dev);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	kfree(par_dev->name);
6278c2ecf20Sopenharmony_ci	kfree(par_dev);
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci/**
6318c2ecf20Sopenharmony_ci *	parport_register_dev_model - register a device on a parallel port
6328c2ecf20Sopenharmony_ci *	@port: port to which the device is attached
6338c2ecf20Sopenharmony_ci *	@name: a name to refer to the device
6348c2ecf20Sopenharmony_ci *	@par_dev_cb: struct containing callbacks
6358c2ecf20Sopenharmony_ci *	@id: device number to be given to the device
6368c2ecf20Sopenharmony_ci *
6378c2ecf20Sopenharmony_ci *	This function, called by parallel port device drivers,
6388c2ecf20Sopenharmony_ci *	declares that a device is connected to a port, and tells the
6398c2ecf20Sopenharmony_ci *	system all it needs to know.
6408c2ecf20Sopenharmony_ci *
6418c2ecf20Sopenharmony_ci *	The struct pardev_cb contains pointer to callbacks. preemption
6428c2ecf20Sopenharmony_ci *	callback function, @preempt, is called when this device driver
6438c2ecf20Sopenharmony_ci *	has claimed access to the port but another device driver wants
6448c2ecf20Sopenharmony_ci *	to use it.  It is given, @private, as its parameter, and should
6458c2ecf20Sopenharmony_ci *	return zero if it is willing for the system to release the port
6468c2ecf20Sopenharmony_ci *	to another driver on its behalf. If it wants to keep control of
6478c2ecf20Sopenharmony_ci *	the port it should return non-zero, and no action will be taken.
6488c2ecf20Sopenharmony_ci *	It is good manners for the driver to try to release the port at
6498c2ecf20Sopenharmony_ci *	the earliest opportunity after its preemption callback rejects a
6508c2ecf20Sopenharmony_ci *	preemption attempt. Note that if a preemption callback is happy
6518c2ecf20Sopenharmony_ci *	for preemption to go ahead, there is no need to release the
6528c2ecf20Sopenharmony_ci *	port; it is done automatically. This function may not block, as
6538c2ecf20Sopenharmony_ci *	it may be called from interrupt context. If the device driver
6548c2ecf20Sopenharmony_ci *	does not support preemption, @preempt can be %NULL.
6558c2ecf20Sopenharmony_ci *
6568c2ecf20Sopenharmony_ci *	The wake-up ("kick") callback function, @wakeup, is called when
6578c2ecf20Sopenharmony_ci *	the port is available to be claimed for exclusive access; that
6588c2ecf20Sopenharmony_ci *	is, parport_claim() is guaranteed to succeed when called from
6598c2ecf20Sopenharmony_ci *	inside the wake-up callback function.  If the driver wants to
6608c2ecf20Sopenharmony_ci *	claim the port it should do so; otherwise, it need not take
6618c2ecf20Sopenharmony_ci *	any action.  This function may not block, as it may be called
6628c2ecf20Sopenharmony_ci *	from interrupt context.  If the device driver does not want to
6638c2ecf20Sopenharmony_ci *	be explicitly invited to claim the port in this way, @wakeup can
6648c2ecf20Sopenharmony_ci *	be %NULL.
6658c2ecf20Sopenharmony_ci *
6668c2ecf20Sopenharmony_ci *	The interrupt handler, @irq_func, is called when an interrupt
6678c2ecf20Sopenharmony_ci *	arrives from the parallel port.  Note that if a device driver
6688c2ecf20Sopenharmony_ci *	wants to use interrupts it should use parport_enable_irq(),
6698c2ecf20Sopenharmony_ci *	and can also check the irq member of the parport structure
6708c2ecf20Sopenharmony_ci *	representing the port.
6718c2ecf20Sopenharmony_ci *
6728c2ecf20Sopenharmony_ci *	The parallel port (lowlevel) driver is the one that has called
6738c2ecf20Sopenharmony_ci *	request_irq() and whose interrupt handler is called first.
6748c2ecf20Sopenharmony_ci *	This handler does whatever needs to be done to the hardware to
6758c2ecf20Sopenharmony_ci *	acknowledge the interrupt (for PC-style ports there is nothing
6768c2ecf20Sopenharmony_ci *	special to be done).  It then tells the IEEE 1284 code about
6778c2ecf20Sopenharmony_ci *	the interrupt, which may involve reacting to an IEEE 1284
6788c2ecf20Sopenharmony_ci *	event depending on the current IEEE 1284 phase.  After this,
6798c2ecf20Sopenharmony_ci *	it calls @irq_func.  Needless to say, @irq_func will be called
6808c2ecf20Sopenharmony_ci *	from interrupt context, and may not block.
6818c2ecf20Sopenharmony_ci *
6828c2ecf20Sopenharmony_ci *	The %PARPORT_DEV_EXCL flag is for preventing port sharing, and
6838c2ecf20Sopenharmony_ci *	so should only be used when sharing the port with other device
6848c2ecf20Sopenharmony_ci *	drivers is impossible and would lead to incorrect behaviour.
6858c2ecf20Sopenharmony_ci *	Use it sparingly!  Normally, @flags will be zero.
6868c2ecf20Sopenharmony_ci *
6878c2ecf20Sopenharmony_ci *	This function returns a pointer to a structure that represents
6888c2ecf20Sopenharmony_ci *	the device on the port, or %NULL if there is not enough memory
6898c2ecf20Sopenharmony_ci *	to allocate space for that structure.
6908c2ecf20Sopenharmony_ci **/
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_cistruct pardevice *
6938c2ecf20Sopenharmony_ciparport_register_dev_model(struct parport *port, const char *name,
6948c2ecf20Sopenharmony_ci			   const struct pardev_cb *par_dev_cb, int id)
6958c2ecf20Sopenharmony_ci{
6968c2ecf20Sopenharmony_ci	struct pardevice *par_dev;
6978c2ecf20Sopenharmony_ci	int ret;
6988c2ecf20Sopenharmony_ci	char *devname;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	if (port->physport->flags & PARPORT_FLAG_EXCL) {
7018c2ecf20Sopenharmony_ci		/* An exclusive device is registered. */
7028c2ecf20Sopenharmony_ci		pr_err("%s: no more devices allowed\n", port->name);
7038c2ecf20Sopenharmony_ci		return NULL;
7048c2ecf20Sopenharmony_ci	}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	if (par_dev_cb->flags & PARPORT_DEV_LURK) {
7078c2ecf20Sopenharmony_ci		if (!par_dev_cb->preempt || !par_dev_cb->wakeup) {
7088c2ecf20Sopenharmony_ci			pr_info("%s: refused to register lurking device (%s) without callbacks\n",
7098c2ecf20Sopenharmony_ci				port->name, name);
7108c2ecf20Sopenharmony_ci			return NULL;
7118c2ecf20Sopenharmony_ci		}
7128c2ecf20Sopenharmony_ci	}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	if (par_dev_cb->flags & PARPORT_DEV_EXCL) {
7158c2ecf20Sopenharmony_ci		if (port->physport->devices) {
7168c2ecf20Sopenharmony_ci			/*
7178c2ecf20Sopenharmony_ci			 * If a device is already registered and this new
7188c2ecf20Sopenharmony_ci			 * device wants exclusive access, then no need to
7198c2ecf20Sopenharmony_ci			 * continue as we can not grant exclusive access to
7208c2ecf20Sopenharmony_ci			 * this device.
7218c2ecf20Sopenharmony_ci			 */
7228c2ecf20Sopenharmony_ci			pr_err("%s: cannot grant exclusive access for device %s\n",
7238c2ecf20Sopenharmony_ci			       port->name, name);
7248c2ecf20Sopenharmony_ci			return NULL;
7258c2ecf20Sopenharmony_ci		}
7268c2ecf20Sopenharmony_ci	}
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	if (!try_module_get(port->ops->owner))
7298c2ecf20Sopenharmony_ci		return NULL;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	parport_get_port(port);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	par_dev = kzalloc(sizeof(*par_dev), GFP_KERNEL);
7348c2ecf20Sopenharmony_ci	if (!par_dev)
7358c2ecf20Sopenharmony_ci		goto err_put_port;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	par_dev->state = kzalloc(sizeof(*par_dev->state), GFP_KERNEL);
7388c2ecf20Sopenharmony_ci	if (!par_dev->state)
7398c2ecf20Sopenharmony_ci		goto err_put_par_dev;
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	devname = kstrdup(name, GFP_KERNEL);
7428c2ecf20Sopenharmony_ci	if (!devname)
7438c2ecf20Sopenharmony_ci		goto err_free_par_dev;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	par_dev->name = devname;
7468c2ecf20Sopenharmony_ci	par_dev->port = port;
7478c2ecf20Sopenharmony_ci	par_dev->daisy = -1;
7488c2ecf20Sopenharmony_ci	par_dev->preempt = par_dev_cb->preempt;
7498c2ecf20Sopenharmony_ci	par_dev->wakeup = par_dev_cb->wakeup;
7508c2ecf20Sopenharmony_ci	par_dev->private = par_dev_cb->private;
7518c2ecf20Sopenharmony_ci	par_dev->flags = par_dev_cb->flags;
7528c2ecf20Sopenharmony_ci	par_dev->irq_func = par_dev_cb->irq_func;
7538c2ecf20Sopenharmony_ci	par_dev->waiting = 0;
7548c2ecf20Sopenharmony_ci	par_dev->timeout = 5 * HZ;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	par_dev->dev.parent = &port->bus_dev;
7578c2ecf20Sopenharmony_ci	par_dev->dev.bus = &parport_bus_type;
7588c2ecf20Sopenharmony_ci	ret = dev_set_name(&par_dev->dev, "%s.%d", devname, id);
7598c2ecf20Sopenharmony_ci	if (ret)
7608c2ecf20Sopenharmony_ci		goto err_free_devname;
7618c2ecf20Sopenharmony_ci	par_dev->dev.release = free_pardevice;
7628c2ecf20Sopenharmony_ci	par_dev->devmodel = true;
7638c2ecf20Sopenharmony_ci	ret = device_register(&par_dev->dev);
7648c2ecf20Sopenharmony_ci	if (ret) {
7658c2ecf20Sopenharmony_ci		kfree(par_dev->state);
7668c2ecf20Sopenharmony_ci		put_device(&par_dev->dev);
7678c2ecf20Sopenharmony_ci		goto err_put_port;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	/* Chain this onto the list */
7718c2ecf20Sopenharmony_ci	par_dev->prev = NULL;
7728c2ecf20Sopenharmony_ci	/*
7738c2ecf20Sopenharmony_ci	 * This function must not run from an irq handler so we don' t need
7748c2ecf20Sopenharmony_ci	 * to clear irq on the local CPU. -arca
7758c2ecf20Sopenharmony_ci	 */
7768c2ecf20Sopenharmony_ci	spin_lock(&port->physport->pardevice_lock);
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	if (par_dev_cb->flags & PARPORT_DEV_EXCL) {
7798c2ecf20Sopenharmony_ci		if (port->physport->devices) {
7808c2ecf20Sopenharmony_ci			spin_unlock(&port->physport->pardevice_lock);
7818c2ecf20Sopenharmony_ci			pr_debug("%s: cannot grant exclusive access for device %s\n",
7828c2ecf20Sopenharmony_ci				 port->name, name);
7838c2ecf20Sopenharmony_ci			kfree(par_dev->state);
7848c2ecf20Sopenharmony_ci			device_unregister(&par_dev->dev);
7858c2ecf20Sopenharmony_ci			goto err_put_port;
7868c2ecf20Sopenharmony_ci		}
7878c2ecf20Sopenharmony_ci		port->flags |= PARPORT_FLAG_EXCL;
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	par_dev->next = port->physport->devices;
7918c2ecf20Sopenharmony_ci	wmb();	/*
7928c2ecf20Sopenharmony_ci		 * Make sure that tmp->next is written before it's
7938c2ecf20Sopenharmony_ci		 * added to the list; see comments marked 'no locking
7948c2ecf20Sopenharmony_ci		 * required'
7958c2ecf20Sopenharmony_ci		 */
7968c2ecf20Sopenharmony_ci	if (port->physport->devices)
7978c2ecf20Sopenharmony_ci		port->physport->devices->prev = par_dev;
7988c2ecf20Sopenharmony_ci	port->physport->devices = par_dev;
7998c2ecf20Sopenharmony_ci	spin_unlock(&port->physport->pardevice_lock);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	init_waitqueue_head(&par_dev->wait_q);
8028c2ecf20Sopenharmony_ci	par_dev->timeslice = parport_default_timeslice;
8038c2ecf20Sopenharmony_ci	par_dev->waitnext = NULL;
8048c2ecf20Sopenharmony_ci	par_dev->waitprev = NULL;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	/*
8078c2ecf20Sopenharmony_ci	 * This has to be run as last thing since init_state may need other
8088c2ecf20Sopenharmony_ci	 * pardevice fields. -arca
8098c2ecf20Sopenharmony_ci	 */
8108c2ecf20Sopenharmony_ci	port->ops->init_state(par_dev, par_dev->state);
8118c2ecf20Sopenharmony_ci	if (!test_and_set_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags)) {
8128c2ecf20Sopenharmony_ci		port->proc_device = par_dev;
8138c2ecf20Sopenharmony_ci		parport_device_proc_register(par_dev);
8148c2ecf20Sopenharmony_ci	}
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	return par_dev;
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_cierr_free_devname:
8198c2ecf20Sopenharmony_ci	kfree(devname);
8208c2ecf20Sopenharmony_cierr_free_par_dev:
8218c2ecf20Sopenharmony_ci	kfree(par_dev->state);
8228c2ecf20Sopenharmony_cierr_put_par_dev:
8238c2ecf20Sopenharmony_ci	if (!par_dev->devmodel)
8248c2ecf20Sopenharmony_ci		kfree(par_dev);
8258c2ecf20Sopenharmony_cierr_put_port:
8268c2ecf20Sopenharmony_ci	parport_put_port(port);
8278c2ecf20Sopenharmony_ci	module_put(port->ops->owner);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	return NULL;
8308c2ecf20Sopenharmony_ci}
8318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_register_dev_model);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci/**
8348c2ecf20Sopenharmony_ci *	parport_unregister_device - deregister a device on a parallel port
8358c2ecf20Sopenharmony_ci *	@dev: pointer to structure representing device
8368c2ecf20Sopenharmony_ci *
8378c2ecf20Sopenharmony_ci *	This undoes the effect of parport_register_device().
8388c2ecf20Sopenharmony_ci **/
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_civoid parport_unregister_device(struct pardevice *dev)
8418c2ecf20Sopenharmony_ci{
8428c2ecf20Sopenharmony_ci	struct parport *port;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci#ifdef PARPORT_PARANOID
8458c2ecf20Sopenharmony_ci	if (!dev) {
8468c2ecf20Sopenharmony_ci		pr_err("%s: passed NULL\n", __func__);
8478c2ecf20Sopenharmony_ci		return;
8488c2ecf20Sopenharmony_ci	}
8498c2ecf20Sopenharmony_ci#endif
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	port = dev->port->physport;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	if (port->proc_device == dev) {
8548c2ecf20Sopenharmony_ci		port->proc_device = NULL;
8558c2ecf20Sopenharmony_ci		clear_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags);
8568c2ecf20Sopenharmony_ci		parport_device_proc_unregister(dev);
8578c2ecf20Sopenharmony_ci	}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	if (port->cad == dev) {
8608c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "%s: %s forgot to release port\n",
8618c2ecf20Sopenharmony_ci		       port->name, dev->name);
8628c2ecf20Sopenharmony_ci		parport_release(dev);
8638c2ecf20Sopenharmony_ci	}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	spin_lock(&port->pardevice_lock);
8668c2ecf20Sopenharmony_ci	if (dev->next)
8678c2ecf20Sopenharmony_ci		dev->next->prev = dev->prev;
8688c2ecf20Sopenharmony_ci	if (dev->prev)
8698c2ecf20Sopenharmony_ci		dev->prev->next = dev->next;
8708c2ecf20Sopenharmony_ci	else
8718c2ecf20Sopenharmony_ci		port->devices = dev->next;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	if (dev->flags & PARPORT_DEV_EXCL)
8748c2ecf20Sopenharmony_ci		port->flags &= ~PARPORT_FLAG_EXCL;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	spin_unlock(&port->pardevice_lock);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	/*
8798c2ecf20Sopenharmony_ci	 * Make sure we haven't left any pointers around in the wait
8808c2ecf20Sopenharmony_ci	 * list.
8818c2ecf20Sopenharmony_ci	 */
8828c2ecf20Sopenharmony_ci	spin_lock_irq(&port->waitlist_lock);
8838c2ecf20Sopenharmony_ci	if (dev->waitprev || dev->waitnext || port->waithead == dev) {
8848c2ecf20Sopenharmony_ci		if (dev->waitprev)
8858c2ecf20Sopenharmony_ci			dev->waitprev->waitnext = dev->waitnext;
8868c2ecf20Sopenharmony_ci		else
8878c2ecf20Sopenharmony_ci			port->waithead = dev->waitnext;
8888c2ecf20Sopenharmony_ci		if (dev->waitnext)
8898c2ecf20Sopenharmony_ci			dev->waitnext->waitprev = dev->waitprev;
8908c2ecf20Sopenharmony_ci		else
8918c2ecf20Sopenharmony_ci			port->waittail = dev->waitprev;
8928c2ecf20Sopenharmony_ci	}
8938c2ecf20Sopenharmony_ci	spin_unlock_irq(&port->waitlist_lock);
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	kfree(dev->state);
8968c2ecf20Sopenharmony_ci	device_unregister(&dev->dev);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	module_put(port->ops->owner);
8998c2ecf20Sopenharmony_ci	parport_put_port(port);
9008c2ecf20Sopenharmony_ci}
9018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_unregister_device);
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci/**
9048c2ecf20Sopenharmony_ci *	parport_find_number - find a parallel port by number
9058c2ecf20Sopenharmony_ci *	@number: parallel port number
9068c2ecf20Sopenharmony_ci *
9078c2ecf20Sopenharmony_ci *	This returns the parallel port with the specified number, or
9088c2ecf20Sopenharmony_ci *	%NULL if there is none.
9098c2ecf20Sopenharmony_ci *
9108c2ecf20Sopenharmony_ci *	There is an implicit parport_get_port() done already; to throw
9118c2ecf20Sopenharmony_ci *	away the reference to the port that parport_find_number()
9128c2ecf20Sopenharmony_ci *	gives you, use parport_put_port().
9138c2ecf20Sopenharmony_ci */
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_cistruct parport *parport_find_number(int number)
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	struct parport *port, *result = NULL;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	if (list_empty(&portlist))
9208c2ecf20Sopenharmony_ci		get_lowlevel_driver();
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	spin_lock(&parportlist_lock);
9238c2ecf20Sopenharmony_ci	list_for_each_entry(port, &portlist, list) {
9248c2ecf20Sopenharmony_ci		if (port->number == number) {
9258c2ecf20Sopenharmony_ci			result = parport_get_port(port);
9268c2ecf20Sopenharmony_ci			break;
9278c2ecf20Sopenharmony_ci		}
9288c2ecf20Sopenharmony_ci	}
9298c2ecf20Sopenharmony_ci	spin_unlock(&parportlist_lock);
9308c2ecf20Sopenharmony_ci	return result;
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_find_number);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci/**
9358c2ecf20Sopenharmony_ci *	parport_find_base - find a parallel port by base address
9368c2ecf20Sopenharmony_ci *	@base: base I/O address
9378c2ecf20Sopenharmony_ci *
9388c2ecf20Sopenharmony_ci *	This returns the parallel port with the specified base
9398c2ecf20Sopenharmony_ci *	address, or %NULL if there is none.
9408c2ecf20Sopenharmony_ci *
9418c2ecf20Sopenharmony_ci *	There is an implicit parport_get_port() done already; to throw
9428c2ecf20Sopenharmony_ci *	away the reference to the port that parport_find_base()
9438c2ecf20Sopenharmony_ci *	gives you, use parport_put_port().
9448c2ecf20Sopenharmony_ci */
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cistruct parport *parport_find_base(unsigned long base)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	struct parport *port, *result = NULL;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	if (list_empty(&portlist))
9518c2ecf20Sopenharmony_ci		get_lowlevel_driver();
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	spin_lock(&parportlist_lock);
9548c2ecf20Sopenharmony_ci	list_for_each_entry(port, &portlist, list) {
9558c2ecf20Sopenharmony_ci		if (port->base == base) {
9568c2ecf20Sopenharmony_ci			result = parport_get_port(port);
9578c2ecf20Sopenharmony_ci			break;
9588c2ecf20Sopenharmony_ci		}
9598c2ecf20Sopenharmony_ci	}
9608c2ecf20Sopenharmony_ci	spin_unlock(&parportlist_lock);
9618c2ecf20Sopenharmony_ci	return result;
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_find_base);
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci/**
9668c2ecf20Sopenharmony_ci *	parport_claim - claim access to a parallel port device
9678c2ecf20Sopenharmony_ci *	@dev: pointer to structure representing a device on the port
9688c2ecf20Sopenharmony_ci *
9698c2ecf20Sopenharmony_ci *	This function will not block and so can be used from interrupt
9708c2ecf20Sopenharmony_ci *	context.  If parport_claim() succeeds in claiming access to
9718c2ecf20Sopenharmony_ci *	the port it returns zero and the port is available to use.  It
9728c2ecf20Sopenharmony_ci *	may fail (returning non-zero) if the port is in use by another
9738c2ecf20Sopenharmony_ci *	driver and that driver is not willing to relinquish control of
9748c2ecf20Sopenharmony_ci *	the port.
9758c2ecf20Sopenharmony_ci **/
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ciint parport_claim(struct pardevice *dev)
9788c2ecf20Sopenharmony_ci{
9798c2ecf20Sopenharmony_ci	struct pardevice *oldcad;
9808c2ecf20Sopenharmony_ci	struct parport *port = dev->port->physport;
9818c2ecf20Sopenharmony_ci	unsigned long flags;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	if (port->cad == dev) {
9848c2ecf20Sopenharmony_ci		pr_info("%s: %s already owner\n", dev->port->name, dev->name);
9858c2ecf20Sopenharmony_ci		return 0;
9868c2ecf20Sopenharmony_ci	}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	/* Preempt any current device */
9898c2ecf20Sopenharmony_ci	write_lock_irqsave(&port->cad_lock, flags);
9908c2ecf20Sopenharmony_ci	oldcad = port->cad;
9918c2ecf20Sopenharmony_ci	if (oldcad) {
9928c2ecf20Sopenharmony_ci		if (oldcad->preempt) {
9938c2ecf20Sopenharmony_ci			if (oldcad->preempt(oldcad->private))
9948c2ecf20Sopenharmony_ci				goto blocked;
9958c2ecf20Sopenharmony_ci			port->ops->save_state(port, dev->state);
9968c2ecf20Sopenharmony_ci		} else
9978c2ecf20Sopenharmony_ci			goto blocked;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci		if (port->cad != oldcad) {
10008c2ecf20Sopenharmony_ci			/*
10018c2ecf20Sopenharmony_ci			 * I think we'll actually deadlock rather than
10028c2ecf20Sopenharmony_ci			 * get here, but just in case..
10038c2ecf20Sopenharmony_ci			 */
10048c2ecf20Sopenharmony_ci			pr_warn("%s: %s released port when preempted!\n",
10058c2ecf20Sopenharmony_ci				port->name, oldcad->name);
10068c2ecf20Sopenharmony_ci			if (port->cad)
10078c2ecf20Sopenharmony_ci				goto blocked;
10088c2ecf20Sopenharmony_ci		}
10098c2ecf20Sopenharmony_ci	}
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	/* Can't fail from now on, so mark ourselves as no longer waiting.  */
10128c2ecf20Sopenharmony_ci	if (dev->waiting & 1) {
10138c2ecf20Sopenharmony_ci		dev->waiting = 0;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci		/* Take ourselves out of the wait list again.  */
10168c2ecf20Sopenharmony_ci		spin_lock_irq(&port->waitlist_lock);
10178c2ecf20Sopenharmony_ci		if (dev->waitprev)
10188c2ecf20Sopenharmony_ci			dev->waitprev->waitnext = dev->waitnext;
10198c2ecf20Sopenharmony_ci		else
10208c2ecf20Sopenharmony_ci			port->waithead = dev->waitnext;
10218c2ecf20Sopenharmony_ci		if (dev->waitnext)
10228c2ecf20Sopenharmony_ci			dev->waitnext->waitprev = dev->waitprev;
10238c2ecf20Sopenharmony_ci		else
10248c2ecf20Sopenharmony_ci			port->waittail = dev->waitprev;
10258c2ecf20Sopenharmony_ci		spin_unlock_irq(&port->waitlist_lock);
10268c2ecf20Sopenharmony_ci		dev->waitprev = dev->waitnext = NULL;
10278c2ecf20Sopenharmony_ci	}
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	/* Now we do the change of devices */
10308c2ecf20Sopenharmony_ci	port->cad = dev;
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci#ifdef CONFIG_PARPORT_1284
10338c2ecf20Sopenharmony_ci	/* If it's a mux port, select it. */
10348c2ecf20Sopenharmony_ci	if (dev->port->muxport >= 0) {
10358c2ecf20Sopenharmony_ci		/* FIXME */
10368c2ecf20Sopenharmony_ci		port->muxsel = dev->port->muxport;
10378c2ecf20Sopenharmony_ci	}
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	/* If it's a daisy chain device, select it. */
10408c2ecf20Sopenharmony_ci	if (dev->daisy >= 0) {
10418c2ecf20Sopenharmony_ci		/* This could be lazier. */
10428c2ecf20Sopenharmony_ci		if (!parport_daisy_select(port, dev->daisy,
10438c2ecf20Sopenharmony_ci					   IEEE1284_MODE_COMPAT))
10448c2ecf20Sopenharmony_ci			port->daisy = dev->daisy;
10458c2ecf20Sopenharmony_ci	}
10468c2ecf20Sopenharmony_ci#endif /* IEEE1284.3 support */
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	/* Restore control registers */
10498c2ecf20Sopenharmony_ci	port->ops->restore_state(port, dev->state);
10508c2ecf20Sopenharmony_ci	write_unlock_irqrestore(&port->cad_lock, flags);
10518c2ecf20Sopenharmony_ci	dev->time = jiffies;
10528c2ecf20Sopenharmony_ci	return 0;
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ciblocked:
10558c2ecf20Sopenharmony_ci	/*
10568c2ecf20Sopenharmony_ci	 * If this is the first time we tried to claim the port, register an
10578c2ecf20Sopenharmony_ci	 * interest.  This is only allowed for devices sleeping in
10588c2ecf20Sopenharmony_ci	 * parport_claim_or_block(), or those with a wakeup function.
10598c2ecf20Sopenharmony_ci	 */
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	/* The cad_lock is still held for writing here */
10628c2ecf20Sopenharmony_ci	if (dev->waiting & 2 || dev->wakeup) {
10638c2ecf20Sopenharmony_ci		spin_lock(&port->waitlist_lock);
10648c2ecf20Sopenharmony_ci		if (test_and_set_bit(0, &dev->waiting) == 0) {
10658c2ecf20Sopenharmony_ci			/* First add ourselves to the end of the wait list. */
10668c2ecf20Sopenharmony_ci			dev->waitnext = NULL;
10678c2ecf20Sopenharmony_ci			dev->waitprev = port->waittail;
10688c2ecf20Sopenharmony_ci			if (port->waittail) {
10698c2ecf20Sopenharmony_ci				port->waittail->waitnext = dev;
10708c2ecf20Sopenharmony_ci				port->waittail = dev;
10718c2ecf20Sopenharmony_ci			} else
10728c2ecf20Sopenharmony_ci				port->waithead = port->waittail = dev;
10738c2ecf20Sopenharmony_ci		}
10748c2ecf20Sopenharmony_ci		spin_unlock(&port->waitlist_lock);
10758c2ecf20Sopenharmony_ci	}
10768c2ecf20Sopenharmony_ci	write_unlock_irqrestore(&port->cad_lock, flags);
10778c2ecf20Sopenharmony_ci	return -EAGAIN;
10788c2ecf20Sopenharmony_ci}
10798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_claim);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci/**
10828c2ecf20Sopenharmony_ci *	parport_claim_or_block - claim access to a parallel port device
10838c2ecf20Sopenharmony_ci *	@dev: pointer to structure representing a device on the port
10848c2ecf20Sopenharmony_ci *
10858c2ecf20Sopenharmony_ci *	This behaves like parport_claim(), but will block if necessary
10868c2ecf20Sopenharmony_ci *	to wait for the port to be free.  A return value of 1
10878c2ecf20Sopenharmony_ci *	indicates that it slept; 0 means that it succeeded without
10888c2ecf20Sopenharmony_ci *	needing to sleep.  A negative error code indicates failure.
10898c2ecf20Sopenharmony_ci **/
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ciint parport_claim_or_block(struct pardevice *dev)
10928c2ecf20Sopenharmony_ci{
10938c2ecf20Sopenharmony_ci	int r;
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	/*
10968c2ecf20Sopenharmony_ci	 * Signal to parport_claim() that we can wait even without a
10978c2ecf20Sopenharmony_ci	 * wakeup function.
10988c2ecf20Sopenharmony_ci	 */
10998c2ecf20Sopenharmony_ci	dev->waiting = 2;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	/* Try to claim the port.  If this fails, we need to sleep.  */
11028c2ecf20Sopenharmony_ci	r = parport_claim(dev);
11038c2ecf20Sopenharmony_ci	if (r == -EAGAIN) {
11048c2ecf20Sopenharmony_ci#ifdef PARPORT_DEBUG_SHARING
11058c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n",
11068c2ecf20Sopenharmony_ci		       dev->name);
11078c2ecf20Sopenharmony_ci#endif
11088c2ecf20Sopenharmony_ci		/*
11098c2ecf20Sopenharmony_ci		 * FIXME!!! Use the proper locking for dev->waiting,
11108c2ecf20Sopenharmony_ci		 * and make this use the "wait_event_interruptible()"
11118c2ecf20Sopenharmony_ci		 * interfaces. The cli/sti that used to be here
11128c2ecf20Sopenharmony_ci		 * did nothing.
11138c2ecf20Sopenharmony_ci		 *
11148c2ecf20Sopenharmony_ci		 * See also parport_release()
11158c2ecf20Sopenharmony_ci		 */
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci		/*
11188c2ecf20Sopenharmony_ci		 * If dev->waiting is clear now, an interrupt
11198c2ecf20Sopenharmony_ci		 * gave us the port and we would deadlock if we slept.
11208c2ecf20Sopenharmony_ci		 */
11218c2ecf20Sopenharmony_ci		if (dev->waiting) {
11228c2ecf20Sopenharmony_ci			wait_event_interruptible(dev->wait_q,
11238c2ecf20Sopenharmony_ci						 !dev->waiting);
11248c2ecf20Sopenharmony_ci			if (signal_pending(current))
11258c2ecf20Sopenharmony_ci				return -EINTR;
11268c2ecf20Sopenharmony_ci			r = 1;
11278c2ecf20Sopenharmony_ci		} else {
11288c2ecf20Sopenharmony_ci			r = 0;
11298c2ecf20Sopenharmony_ci#ifdef PARPORT_DEBUG_SHARING
11308c2ecf20Sopenharmony_ci			printk(KERN_DEBUG "%s: didn't sleep in parport_claim_or_block()\n",
11318c2ecf20Sopenharmony_ci			       dev->name);
11328c2ecf20Sopenharmony_ci#endif
11338c2ecf20Sopenharmony_ci		}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci#ifdef PARPORT_DEBUG_SHARING
11368c2ecf20Sopenharmony_ci		if (dev->port->physport->cad != dev)
11378c2ecf20Sopenharmony_ci			printk(KERN_DEBUG "%s: exiting parport_claim_or_block but %s owns port!\n",
11388c2ecf20Sopenharmony_ci			       dev->name, dev->port->physport->cad ?
11398c2ecf20Sopenharmony_ci			       dev->port->physport->cad->name : "nobody");
11408c2ecf20Sopenharmony_ci#endif
11418c2ecf20Sopenharmony_ci	}
11428c2ecf20Sopenharmony_ci	dev->waiting = 0;
11438c2ecf20Sopenharmony_ci	return r;
11448c2ecf20Sopenharmony_ci}
11458c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_claim_or_block);
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci/**
11488c2ecf20Sopenharmony_ci *	parport_release - give up access to a parallel port device
11498c2ecf20Sopenharmony_ci *	@dev: pointer to structure representing parallel port device
11508c2ecf20Sopenharmony_ci *
11518c2ecf20Sopenharmony_ci *	This function cannot fail, but it should not be called without
11528c2ecf20Sopenharmony_ci *	the port claimed.  Similarly, if the port is already claimed
11538c2ecf20Sopenharmony_ci *	you should not try claiming it again.
11548c2ecf20Sopenharmony_ci **/
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_civoid parport_release(struct pardevice *dev)
11578c2ecf20Sopenharmony_ci{
11588c2ecf20Sopenharmony_ci	struct parport *port = dev->port->physport;
11598c2ecf20Sopenharmony_ci	struct pardevice *pd;
11608c2ecf20Sopenharmony_ci	unsigned long flags;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	/* Make sure that dev is the current device */
11638c2ecf20Sopenharmony_ci	write_lock_irqsave(&port->cad_lock, flags);
11648c2ecf20Sopenharmony_ci	if (port->cad != dev) {
11658c2ecf20Sopenharmony_ci		write_unlock_irqrestore(&port->cad_lock, flags);
11668c2ecf20Sopenharmony_ci		pr_warn("%s: %s tried to release parport when not owner\n",
11678c2ecf20Sopenharmony_ci			port->name, dev->name);
11688c2ecf20Sopenharmony_ci		return;
11698c2ecf20Sopenharmony_ci	}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci#ifdef CONFIG_PARPORT_1284
11728c2ecf20Sopenharmony_ci	/* If this is on a mux port, deselect it. */
11738c2ecf20Sopenharmony_ci	if (dev->port->muxport >= 0) {
11748c2ecf20Sopenharmony_ci		/* FIXME */
11758c2ecf20Sopenharmony_ci		port->muxsel = -1;
11768c2ecf20Sopenharmony_ci	}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	/* If this is a daisy device, deselect it. */
11798c2ecf20Sopenharmony_ci	if (dev->daisy >= 0) {
11808c2ecf20Sopenharmony_ci		parport_daisy_deselect_all(port);
11818c2ecf20Sopenharmony_ci		port->daisy = -1;
11828c2ecf20Sopenharmony_ci	}
11838c2ecf20Sopenharmony_ci#endif
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	port->cad = NULL;
11868c2ecf20Sopenharmony_ci	write_unlock_irqrestore(&port->cad_lock, flags);
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	/* Save control registers */
11898c2ecf20Sopenharmony_ci	port->ops->save_state(port, dev->state);
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	/*
11928c2ecf20Sopenharmony_ci	 * If anybody is waiting, find out who's been there longest and
11938c2ecf20Sopenharmony_ci	 * then wake them up. (Note: no locking required)
11948c2ecf20Sopenharmony_ci	 */
11958c2ecf20Sopenharmony_ci	/* !!! LOCKING IS NEEDED HERE */
11968c2ecf20Sopenharmony_ci	for (pd = port->waithead; pd; pd = pd->waitnext) {
11978c2ecf20Sopenharmony_ci		if (pd->waiting & 2) { /* sleeping in claim_or_block */
11988c2ecf20Sopenharmony_ci			parport_claim(pd);
11998c2ecf20Sopenharmony_ci			if (waitqueue_active(&pd->wait_q))
12008c2ecf20Sopenharmony_ci				wake_up_interruptible(&pd->wait_q);
12018c2ecf20Sopenharmony_ci			return;
12028c2ecf20Sopenharmony_ci		} else if (pd->wakeup) {
12038c2ecf20Sopenharmony_ci			pd->wakeup(pd->private);
12048c2ecf20Sopenharmony_ci			if (dev->port->cad) /* racy but no matter */
12058c2ecf20Sopenharmony_ci				return;
12068c2ecf20Sopenharmony_ci		} else {
12078c2ecf20Sopenharmony_ci			pr_err("%s: don't know how to wake %s\n",
12088c2ecf20Sopenharmony_ci			       port->name, pd->name);
12098c2ecf20Sopenharmony_ci		}
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	/*
12138c2ecf20Sopenharmony_ci	 * Nobody was waiting, so walk the list to see if anyone is
12148c2ecf20Sopenharmony_ci	 * interested in being woken up. (Note: no locking required)
12158c2ecf20Sopenharmony_ci	 */
12168c2ecf20Sopenharmony_ci	/* !!! LOCKING IS NEEDED HERE */
12178c2ecf20Sopenharmony_ci	for (pd = port->devices; !port->cad && pd; pd = pd->next) {
12188c2ecf20Sopenharmony_ci		if (pd->wakeup && pd != dev)
12198c2ecf20Sopenharmony_ci			pd->wakeup(pd->private);
12208c2ecf20Sopenharmony_ci	}
12218c2ecf20Sopenharmony_ci}
12228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_release);
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ciirqreturn_t parport_irq_handler(int irq, void *dev_id)
12258c2ecf20Sopenharmony_ci{
12268c2ecf20Sopenharmony_ci	struct parport *port = dev_id;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	parport_generic_irq(port);
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
12318c2ecf20Sopenharmony_ci}
12328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parport_irq_handler);
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1235