162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Parallel-port resource manager code. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> 562306a36Sopenharmony_ci * Tim Waugh <tim@cyberelk.demon.co.uk> 662306a36Sopenharmony_ci * Jose Renau <renau@acm.org> 762306a36Sopenharmony_ci * Philip Blundell <philb@gnu.org> 862306a36Sopenharmony_ci * Andrea Arcangeli 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * based on work by Grant Guenther <grant@torque.net> 1162306a36Sopenharmony_ci * and Philip Blundell 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Any part of this program may be used in documents licensed under 1462306a36Sopenharmony_ci * the GNU Free Documentation License, Version 1.1 or any later version 1562306a36Sopenharmony_ci * published by the Free Software Foundation. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#undef PARPORT_DEBUG_SHARING /* undef for production */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/string.h> 2262306a36Sopenharmony_ci#include <linux/threads.h> 2362306a36Sopenharmony_ci#include <linux/parport.h> 2462306a36Sopenharmony_ci#include <linux/delay.h> 2562306a36Sopenharmony_ci#include <linux/errno.h> 2662306a36Sopenharmony_ci#include <linux/interrupt.h> 2762306a36Sopenharmony_ci#include <linux/ioport.h> 2862306a36Sopenharmony_ci#include <linux/kernel.h> 2962306a36Sopenharmony_ci#include <linux/slab.h> 3062306a36Sopenharmony_ci#include <linux/sched/signal.h> 3162306a36Sopenharmony_ci#include <linux/kmod.h> 3262306a36Sopenharmony_ci#include <linux/device.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include <linux/spinlock.h> 3562306a36Sopenharmony_ci#include <linux/mutex.h> 3662306a36Sopenharmony_ci#include <asm/irq.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#undef PARPORT_PARANOID 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define PARPORT_DEFAULT_TIMESLICE (HZ/5) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciunsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE; 4362306a36Sopenharmony_ciint parport_default_spintime = DEFAULT_SPIN_TIME; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic LIST_HEAD(portlist); 4662306a36Sopenharmony_cistatic DEFINE_SPINLOCK(parportlist_lock); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* list of all allocated ports, sorted by ->number */ 4962306a36Sopenharmony_cistatic LIST_HEAD(all_ports); 5062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(full_list_lock); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic LIST_HEAD(drivers); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic DEFINE_MUTEX(registration_lock); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* What you can do to a port that's gone away.. */ 5762306a36Sopenharmony_cistatic void dead_write_lines(struct parport *p, unsigned char b){} 5862306a36Sopenharmony_cistatic unsigned char dead_read_lines(struct parport *p) { return 0; } 5962306a36Sopenharmony_cistatic unsigned char dead_frob_lines(struct parport *p, unsigned char b, 6062306a36Sopenharmony_ci unsigned char c) { return 0; } 6162306a36Sopenharmony_cistatic void dead_onearg(struct parport *p){} 6262306a36Sopenharmony_cistatic void dead_initstate(struct pardevice *d, struct parport_state *s) { } 6362306a36Sopenharmony_cistatic void dead_state(struct parport *p, struct parport_state *s) { } 6462306a36Sopenharmony_cistatic size_t dead_write(struct parport *p, const void *b, size_t l, int f) 6562306a36Sopenharmony_ci{ return 0; } 6662306a36Sopenharmony_cistatic size_t dead_read(struct parport *p, void *b, size_t l, int f) 6762306a36Sopenharmony_ci{ return 0; } 6862306a36Sopenharmony_cistatic struct parport_operations dead_ops = { 6962306a36Sopenharmony_ci .write_data = dead_write_lines, /* data */ 7062306a36Sopenharmony_ci .read_data = dead_read_lines, 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci .write_control = dead_write_lines, /* control */ 7362306a36Sopenharmony_ci .read_control = dead_read_lines, 7462306a36Sopenharmony_ci .frob_control = dead_frob_lines, 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci .read_status = dead_read_lines, /* status */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci .enable_irq = dead_onearg, /* enable_irq */ 7962306a36Sopenharmony_ci .disable_irq = dead_onearg, /* disable_irq */ 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci .data_forward = dead_onearg, /* data_forward */ 8262306a36Sopenharmony_ci .data_reverse = dead_onearg, /* data_reverse */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci .init_state = dead_initstate, /* init_state */ 8562306a36Sopenharmony_ci .save_state = dead_state, 8662306a36Sopenharmony_ci .restore_state = dead_state, 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci .epp_write_data = dead_write, /* epp */ 8962306a36Sopenharmony_ci .epp_read_data = dead_read, 9062306a36Sopenharmony_ci .epp_write_addr = dead_write, 9162306a36Sopenharmony_ci .epp_read_addr = dead_read, 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci .ecp_write_data = dead_write, /* ecp */ 9462306a36Sopenharmony_ci .ecp_read_data = dead_read, 9562306a36Sopenharmony_ci .ecp_write_addr = dead_write, 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci .compat_write_data = dead_write, /* compat */ 9862306a36Sopenharmony_ci .nibble_read_data = dead_read, /* nibble */ 9962306a36Sopenharmony_ci .byte_read_data = dead_read, /* byte */ 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci .owner = NULL, 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic struct device_type parport_device_type = { 10562306a36Sopenharmony_ci .name = "parport", 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic int is_parport(struct device *dev) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci return dev->type == &parport_device_type; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic int parport_probe(struct device *dev) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct parport_driver *drv; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (is_parport(dev)) 11862306a36Sopenharmony_ci return -ENODEV; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci drv = to_parport_driver(dev->driver); 12162306a36Sopenharmony_ci if (!drv->probe) { 12262306a36Sopenharmony_ci /* if driver has not defined a custom probe */ 12362306a36Sopenharmony_ci struct pardevice *par_dev = to_pardevice(dev); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (strcmp(par_dev->name, drv->name)) 12662306a36Sopenharmony_ci return -ENODEV; 12762306a36Sopenharmony_ci return 0; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci /* if driver defined its own probe */ 13062306a36Sopenharmony_ci return drv->probe(to_pardevice(dev)); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic struct bus_type parport_bus_type = { 13462306a36Sopenharmony_ci .name = "parport", 13562306a36Sopenharmony_ci .probe = parport_probe, 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ciint parport_bus_init(void) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci return bus_register(&parport_bus_type); 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_civoid parport_bus_exit(void) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci bus_unregister(&parport_bus_type); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* 14962306a36Sopenharmony_ci * iterates through all the drivers registered with the bus and sends the port 15062306a36Sopenharmony_ci * details to the match_port callback of the driver, so that the driver can 15162306a36Sopenharmony_ci * know about the new port that just registered with the bus and decide if it 15262306a36Sopenharmony_ci * wants to use this new port. 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_cistatic int driver_check(struct device_driver *dev_drv, void *_port) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct parport *port = _port; 15762306a36Sopenharmony_ci struct parport_driver *drv = to_parport_driver(dev_drv); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci if (drv->match_port) 16062306a36Sopenharmony_ci drv->match_port(port); 16162306a36Sopenharmony_ci return 0; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/* Call attach(port) for each registered driver. */ 16562306a36Sopenharmony_cistatic void attach_driver_chain(struct parport *port) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci /* caller has exclusive registration_lock */ 16862306a36Sopenharmony_ci struct parport_driver *drv; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci list_for_each_entry(drv, &drivers, list) 17162306a36Sopenharmony_ci drv->attach(port); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* 17462306a36Sopenharmony_ci * call the driver_check function of the drivers registered in 17562306a36Sopenharmony_ci * new device model 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci bus_for_each_drv(&parport_bus_type, NULL, port, driver_check); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int driver_detach(struct device_driver *_drv, void *_port) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct parport *port = _port; 18462306a36Sopenharmony_ci struct parport_driver *drv = to_parport_driver(_drv); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (drv->detach) 18762306a36Sopenharmony_ci drv->detach(port); 18862306a36Sopenharmony_ci return 0; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci/* Call detach(port) for each registered driver. */ 19262306a36Sopenharmony_cistatic void detach_driver_chain(struct parport *port) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct parport_driver *drv; 19562306a36Sopenharmony_ci /* caller has exclusive registration_lock */ 19662306a36Sopenharmony_ci list_for_each_entry(drv, &drivers, list) 19762306a36Sopenharmony_ci drv->detach(port); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* 20062306a36Sopenharmony_ci * call the detach function of the drivers registered in 20162306a36Sopenharmony_ci * new device model 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci bus_for_each_drv(&parport_bus_type, NULL, port, driver_detach); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* Ask kmod for some lowlevel drivers. */ 20862306a36Sopenharmony_cistatic void get_lowlevel_driver(void) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci /* 21162306a36Sopenharmony_ci * There is no actual module called this: you should set 21262306a36Sopenharmony_ci * up an alias for modutils. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci request_module("parport_lowlevel"); 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci/* 21862306a36Sopenharmony_ci * iterates through all the devices connected to the bus and sends the device 21962306a36Sopenharmony_ci * details to the match_port callback of the driver, so that the driver can 22062306a36Sopenharmony_ci * know what are all the ports that are connected to the bus and choose the 22162306a36Sopenharmony_ci * port to which it wants to register its device. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_cistatic int port_check(struct device *dev, void *dev_drv) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci struct parport_driver *drv = dev_drv; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci /* only send ports, do not send other devices connected to bus */ 22862306a36Sopenharmony_ci if (is_parport(dev)) 22962306a36Sopenharmony_ci drv->match_port(to_parport_dev(dev)); 23062306a36Sopenharmony_ci return 0; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* 23462306a36Sopenharmony_ci * Iterates through all the devices connected to the bus and return 1 23562306a36Sopenharmony_ci * if the device is a parallel port. 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int port_detect(struct device *dev, void *dev_drv) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci if (is_parport(dev)) 24162306a36Sopenharmony_ci return 1; 24262306a36Sopenharmony_ci return 0; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci/** 24662306a36Sopenharmony_ci * __parport_register_driver - register a parallel port device driver 24762306a36Sopenharmony_ci * @drv: structure describing the driver 24862306a36Sopenharmony_ci * @owner: owner module of drv 24962306a36Sopenharmony_ci * @mod_name: module name string 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * This can be called by a parallel port device driver in order 25262306a36Sopenharmony_ci * to receive notifications about ports being found in the 25362306a36Sopenharmony_ci * system, as well as ports no longer available. 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * If devmodel is true then the new device model is used 25662306a36Sopenharmony_ci * for registration. 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * The @drv structure is allocated by the caller and must not be 25962306a36Sopenharmony_ci * deallocated until after calling parport_unregister_driver(). 26062306a36Sopenharmony_ci * 26162306a36Sopenharmony_ci * If using the non device model: 26262306a36Sopenharmony_ci * The driver's attach() function may block. The port that 26362306a36Sopenharmony_ci * attach() is given will be valid for the duration of the 26462306a36Sopenharmony_ci * callback, but if the driver wants to take a copy of the 26562306a36Sopenharmony_ci * pointer it must call parport_get_port() to do so. Calling 26662306a36Sopenharmony_ci * parport_register_device() on that port will do this for you. 26762306a36Sopenharmony_ci * 26862306a36Sopenharmony_ci * The driver's detach() function may block. The port that 26962306a36Sopenharmony_ci * detach() is given will be valid for the duration of the 27062306a36Sopenharmony_ci * callback, but if the driver wants to take a copy of the 27162306a36Sopenharmony_ci * pointer it must call parport_get_port() to do so. 27262306a36Sopenharmony_ci * 27362306a36Sopenharmony_ci * 27462306a36Sopenharmony_ci * Returns 0 on success. The non device model will always succeeds. 27562306a36Sopenharmony_ci * but the new device model can fail and will return the error code. 27662306a36Sopenharmony_ci **/ 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ciint __parport_register_driver(struct parport_driver *drv, struct module *owner, 27962306a36Sopenharmony_ci const char *mod_name) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci /* using device model */ 28262306a36Sopenharmony_ci int ret; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* initialize common driver fields */ 28562306a36Sopenharmony_ci drv->driver.name = drv->name; 28662306a36Sopenharmony_ci drv->driver.bus = &parport_bus_type; 28762306a36Sopenharmony_ci drv->driver.owner = owner; 28862306a36Sopenharmony_ci drv->driver.mod_name = mod_name; 28962306a36Sopenharmony_ci ret = driver_register(&drv->driver); 29062306a36Sopenharmony_ci if (ret) 29162306a36Sopenharmony_ci return ret; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * check if bus has any parallel port registered, if 29562306a36Sopenharmony_ci * none is found then load the lowlevel driver. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_ci ret = bus_for_each_dev(&parport_bus_type, NULL, NULL, 29862306a36Sopenharmony_ci port_detect); 29962306a36Sopenharmony_ci if (!ret) 30062306a36Sopenharmony_ci get_lowlevel_driver(); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci mutex_lock(®istration_lock); 30362306a36Sopenharmony_ci if (drv->match_port) 30462306a36Sopenharmony_ci bus_for_each_dev(&parport_bus_type, NULL, drv, 30562306a36Sopenharmony_ci port_check); 30662306a36Sopenharmony_ci mutex_unlock(®istration_lock); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ciEXPORT_SYMBOL(__parport_register_driver); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic int port_detach(struct device *dev, void *_drv) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct parport_driver *drv = _drv; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (is_parport(dev) && drv->detach) 31762306a36Sopenharmony_ci drv->detach(to_parport_dev(dev)); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/** 32362306a36Sopenharmony_ci * parport_unregister_driver - deregister a parallel port device driver 32462306a36Sopenharmony_ci * @drv: structure describing the driver that was given to 32562306a36Sopenharmony_ci * parport_register_driver() 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * This should be called by a parallel port device driver that 32862306a36Sopenharmony_ci * has registered itself using parport_register_driver() when it 32962306a36Sopenharmony_ci * is about to be unloaded. 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci * When it returns, the driver's attach() routine will no longer 33262306a36Sopenharmony_ci * be called, and for each port that attach() was called for, the 33362306a36Sopenharmony_ci * detach() routine will have been called. 33462306a36Sopenharmony_ci * 33562306a36Sopenharmony_ci * All the driver's attach() and detach() calls are guaranteed to have 33662306a36Sopenharmony_ci * finished by the time this function returns. 33762306a36Sopenharmony_ci **/ 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_civoid parport_unregister_driver(struct parport_driver *drv) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci mutex_lock(®istration_lock); 34262306a36Sopenharmony_ci bus_for_each_dev(&parport_bus_type, NULL, drv, port_detach); 34362306a36Sopenharmony_ci driver_unregister(&drv->driver); 34462306a36Sopenharmony_ci mutex_unlock(®istration_lock); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ciEXPORT_SYMBOL(parport_unregister_driver); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic void free_port(struct device *dev) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci int d; 35162306a36Sopenharmony_ci struct parport *port = to_parport_dev(dev); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci spin_lock(&full_list_lock); 35462306a36Sopenharmony_ci list_del(&port->full_list); 35562306a36Sopenharmony_ci spin_unlock(&full_list_lock); 35662306a36Sopenharmony_ci for (d = 0; d < 5; d++) { 35762306a36Sopenharmony_ci kfree(port->probe_info[d].class_name); 35862306a36Sopenharmony_ci kfree(port->probe_info[d].mfr); 35962306a36Sopenharmony_ci kfree(port->probe_info[d].model); 36062306a36Sopenharmony_ci kfree(port->probe_info[d].cmdset); 36162306a36Sopenharmony_ci kfree(port->probe_info[d].description); 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci kfree(port->name); 36562306a36Sopenharmony_ci kfree(port); 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci/** 36962306a36Sopenharmony_ci * parport_get_port - increment a port's reference count 37062306a36Sopenharmony_ci * @port: the port 37162306a36Sopenharmony_ci * 37262306a36Sopenharmony_ci * This ensures that a struct parport pointer remains valid 37362306a36Sopenharmony_ci * until the matching parport_put_port() call. 37462306a36Sopenharmony_ci **/ 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistruct parport *parport_get_port(struct parport *port) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct device *dev = get_device(&port->bus_dev); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci return to_parport_dev(dev); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ciEXPORT_SYMBOL(parport_get_port); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_civoid parport_del_port(struct parport *port) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci device_unregister(&port->bus_dev); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ciEXPORT_SYMBOL(parport_del_port); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci/** 39162306a36Sopenharmony_ci * parport_put_port - decrement a port's reference count 39262306a36Sopenharmony_ci * @port: the port 39362306a36Sopenharmony_ci * 39462306a36Sopenharmony_ci * This should be called once for each call to parport_get_port(), 39562306a36Sopenharmony_ci * once the port is no longer needed. When the reference count reaches 39662306a36Sopenharmony_ci * zero (port is no longer used), free_port is called. 39762306a36Sopenharmony_ci **/ 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_civoid parport_put_port(struct parport *port) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci put_device(&port->bus_dev); 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ciEXPORT_SYMBOL(parport_put_port); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci/** 40662306a36Sopenharmony_ci * parport_register_port - register a parallel port 40762306a36Sopenharmony_ci * @base: base I/O address 40862306a36Sopenharmony_ci * @irq: IRQ line 40962306a36Sopenharmony_ci * @dma: DMA channel 41062306a36Sopenharmony_ci * @ops: pointer to the port driver's port operations structure 41162306a36Sopenharmony_ci * 41262306a36Sopenharmony_ci * When a parallel port (lowlevel) driver finds a port that 41362306a36Sopenharmony_ci * should be made available to parallel port device drivers, it 41462306a36Sopenharmony_ci * should call parport_register_port(). The @base, @irq, and 41562306a36Sopenharmony_ci * @dma parameters are for the convenience of port drivers, and 41662306a36Sopenharmony_ci * for ports where they aren't meaningful needn't be set to 41762306a36Sopenharmony_ci * anything special. They can be altered afterwards by adjusting 41862306a36Sopenharmony_ci * the relevant members of the parport structure that is returned 41962306a36Sopenharmony_ci * and represents the port. They should not be tampered with 42062306a36Sopenharmony_ci * after calling parport_announce_port, however. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * If there are parallel port device drivers in the system that 42362306a36Sopenharmony_ci * have registered themselves using parport_register_driver(), 42462306a36Sopenharmony_ci * they are not told about the port at this time; that is done by 42562306a36Sopenharmony_ci * parport_announce_port(). 42662306a36Sopenharmony_ci * 42762306a36Sopenharmony_ci * The @ops structure is allocated by the caller, and must not be 42862306a36Sopenharmony_ci * deallocated before calling parport_remove_port(). 42962306a36Sopenharmony_ci * 43062306a36Sopenharmony_ci * If there is no memory to allocate a new parport structure, 43162306a36Sopenharmony_ci * this function will return %NULL. 43262306a36Sopenharmony_ci **/ 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistruct parport *parport_register_port(unsigned long base, int irq, int dma, 43562306a36Sopenharmony_ci struct parport_operations *ops) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct list_head *l; 43862306a36Sopenharmony_ci struct parport *tmp; 43962306a36Sopenharmony_ci int num; 44062306a36Sopenharmony_ci int device; 44162306a36Sopenharmony_ci char *name; 44262306a36Sopenharmony_ci int ret; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci tmp = kzalloc(sizeof(struct parport), GFP_KERNEL); 44562306a36Sopenharmony_ci if (!tmp) 44662306a36Sopenharmony_ci return NULL; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* Init our structure */ 44962306a36Sopenharmony_ci tmp->base = base; 45062306a36Sopenharmony_ci tmp->irq = irq; 45162306a36Sopenharmony_ci tmp->dma = dma; 45262306a36Sopenharmony_ci tmp->muxport = tmp->daisy = tmp->muxsel = -1; 45362306a36Sopenharmony_ci tmp->modes = 0; 45462306a36Sopenharmony_ci INIT_LIST_HEAD(&tmp->list); 45562306a36Sopenharmony_ci tmp->devices = tmp->cad = NULL; 45662306a36Sopenharmony_ci tmp->flags = 0; 45762306a36Sopenharmony_ci tmp->ops = ops; 45862306a36Sopenharmony_ci tmp->physport = tmp; 45962306a36Sopenharmony_ci memset(tmp->probe_info, 0, 5 * sizeof(struct parport_device_info)); 46062306a36Sopenharmony_ci rwlock_init(&tmp->cad_lock); 46162306a36Sopenharmony_ci spin_lock_init(&tmp->waitlist_lock); 46262306a36Sopenharmony_ci spin_lock_init(&tmp->pardevice_lock); 46362306a36Sopenharmony_ci tmp->ieee1284.mode = IEEE1284_MODE_COMPAT; 46462306a36Sopenharmony_ci tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE; 46562306a36Sopenharmony_ci sema_init(&tmp->ieee1284.irq, 0); 46662306a36Sopenharmony_ci tmp->spintime = parport_default_spintime; 46762306a36Sopenharmony_ci atomic_set(&tmp->ref_count, 1); 46862306a36Sopenharmony_ci INIT_LIST_HEAD(&tmp->full_list); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci name = kmalloc(PARPORT_NAME_MAX_LEN, GFP_KERNEL); 47162306a36Sopenharmony_ci if (!name) { 47262306a36Sopenharmony_ci kfree(tmp); 47362306a36Sopenharmony_ci return NULL; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci /* Search for the lowest free parport number. */ 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci spin_lock(&full_list_lock); 47862306a36Sopenharmony_ci for (l = all_ports.next, num = 0; l != &all_ports; l = l->next, num++) { 47962306a36Sopenharmony_ci struct parport *p = list_entry(l, struct parport, full_list); 48062306a36Sopenharmony_ci if (p->number != num) 48162306a36Sopenharmony_ci break; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci tmp->portnum = tmp->number = num; 48462306a36Sopenharmony_ci list_add_tail(&tmp->full_list, l); 48562306a36Sopenharmony_ci spin_unlock(&full_list_lock); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* 48862306a36Sopenharmony_ci * Now that the portnum is known finish doing the Init. 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci sprintf(name, "parport%d", tmp->portnum = tmp->number); 49162306a36Sopenharmony_ci tmp->name = name; 49262306a36Sopenharmony_ci tmp->bus_dev.bus = &parport_bus_type; 49362306a36Sopenharmony_ci tmp->bus_dev.release = free_port; 49462306a36Sopenharmony_ci dev_set_name(&tmp->bus_dev, name); 49562306a36Sopenharmony_ci tmp->bus_dev.type = &parport_device_type; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci for (device = 0; device < 5; device++) 49862306a36Sopenharmony_ci /* assume the worst */ 49962306a36Sopenharmony_ci tmp->probe_info[device].class = PARPORT_CLASS_LEGACY; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci tmp->waithead = tmp->waittail = NULL; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci ret = device_register(&tmp->bus_dev); 50462306a36Sopenharmony_ci if (ret) { 50562306a36Sopenharmony_ci put_device(&tmp->bus_dev); 50662306a36Sopenharmony_ci return NULL; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci return tmp; 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ciEXPORT_SYMBOL(parport_register_port); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci/** 51462306a36Sopenharmony_ci * parport_announce_port - tell device drivers about a parallel port 51562306a36Sopenharmony_ci * @port: parallel port to announce 51662306a36Sopenharmony_ci * 51762306a36Sopenharmony_ci * After a port driver has registered a parallel port with 51862306a36Sopenharmony_ci * parport_register_port, and performed any necessary 51962306a36Sopenharmony_ci * initialisation or adjustments, it should call 52062306a36Sopenharmony_ci * parport_announce_port() in order to notify all device drivers 52162306a36Sopenharmony_ci * that have called parport_register_driver(). Their attach() 52262306a36Sopenharmony_ci * functions will be called, with @port as the parameter. 52362306a36Sopenharmony_ci **/ 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_civoid parport_announce_port(struct parport *port) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci int i; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci#ifdef CONFIG_PARPORT_1284 53062306a36Sopenharmony_ci /* Analyse the IEEE1284.3 topology of the port. */ 53162306a36Sopenharmony_ci parport_daisy_init(port); 53262306a36Sopenharmony_ci#endif 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (!port->dev) 53562306a36Sopenharmony_ci pr_warn("%s: fix this legacy no-device port driver!\n", 53662306a36Sopenharmony_ci port->name); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci parport_proc_register(port); 53962306a36Sopenharmony_ci mutex_lock(®istration_lock); 54062306a36Sopenharmony_ci spin_lock_irq(&parportlist_lock); 54162306a36Sopenharmony_ci list_add_tail(&port->list, &portlist); 54262306a36Sopenharmony_ci for (i = 1; i < 3; i++) { 54362306a36Sopenharmony_ci struct parport *slave = port->slaves[i-1]; 54462306a36Sopenharmony_ci if (slave) 54562306a36Sopenharmony_ci list_add_tail(&slave->list, &portlist); 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci spin_unlock_irq(&parportlist_lock); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci /* Let drivers know that new port(s) has arrived. */ 55062306a36Sopenharmony_ci attach_driver_chain(port); 55162306a36Sopenharmony_ci for (i = 1; i < 3; i++) { 55262306a36Sopenharmony_ci struct parport *slave = port->slaves[i-1]; 55362306a36Sopenharmony_ci if (slave) 55462306a36Sopenharmony_ci attach_driver_chain(slave); 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci mutex_unlock(®istration_lock); 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ciEXPORT_SYMBOL(parport_announce_port); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci/** 56162306a36Sopenharmony_ci * parport_remove_port - deregister a parallel port 56262306a36Sopenharmony_ci * @port: parallel port to deregister 56362306a36Sopenharmony_ci * 56462306a36Sopenharmony_ci * When a parallel port driver is forcibly unloaded, or a 56562306a36Sopenharmony_ci * parallel port becomes inaccessible, the port driver must call 56662306a36Sopenharmony_ci * this function in order to deal with device drivers that still 56762306a36Sopenharmony_ci * want to use it. 56862306a36Sopenharmony_ci * 56962306a36Sopenharmony_ci * The parport structure associated with the port has its 57062306a36Sopenharmony_ci * operations structure replaced with one containing 'null' 57162306a36Sopenharmony_ci * operations that return errors or just don't do anything. 57262306a36Sopenharmony_ci * 57362306a36Sopenharmony_ci * Any drivers that have registered themselves using 57462306a36Sopenharmony_ci * parport_register_driver() are notified that the port is no 57562306a36Sopenharmony_ci * longer accessible by having their detach() routines called 57662306a36Sopenharmony_ci * with @port as the parameter. 57762306a36Sopenharmony_ci **/ 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_civoid parport_remove_port(struct parport *port) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci int i; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci mutex_lock(®istration_lock); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /* Spread the word. */ 58662306a36Sopenharmony_ci detach_driver_chain(port); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci#ifdef CONFIG_PARPORT_1284 58962306a36Sopenharmony_ci /* Forget the IEEE1284.3 topology of the port. */ 59062306a36Sopenharmony_ci parport_daisy_fini(port); 59162306a36Sopenharmony_ci for (i = 1; i < 3; i++) { 59262306a36Sopenharmony_ci struct parport *slave = port->slaves[i-1]; 59362306a36Sopenharmony_ci if (!slave) 59462306a36Sopenharmony_ci continue; 59562306a36Sopenharmony_ci detach_driver_chain(slave); 59662306a36Sopenharmony_ci parport_daisy_fini(slave); 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci#endif 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci port->ops = &dead_ops; 60162306a36Sopenharmony_ci spin_lock(&parportlist_lock); 60262306a36Sopenharmony_ci list_del_init(&port->list); 60362306a36Sopenharmony_ci for (i = 1; i < 3; i++) { 60462306a36Sopenharmony_ci struct parport *slave = port->slaves[i-1]; 60562306a36Sopenharmony_ci if (slave) 60662306a36Sopenharmony_ci list_del_init(&slave->list); 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci spin_unlock(&parportlist_lock); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci mutex_unlock(®istration_lock); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci parport_proc_unregister(port); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci for (i = 1; i < 3; i++) { 61562306a36Sopenharmony_ci struct parport *slave = port->slaves[i-1]; 61662306a36Sopenharmony_ci if (slave) 61762306a36Sopenharmony_ci parport_put_port(slave); 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci} 62062306a36Sopenharmony_ciEXPORT_SYMBOL(parport_remove_port); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic void free_pardevice(struct device *dev) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci struct pardevice *par_dev = to_pardevice(dev); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci kfree(par_dev->name); 62762306a36Sopenharmony_ci kfree(par_dev); 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci/** 63162306a36Sopenharmony_ci * parport_register_dev_model - register a device on a parallel port 63262306a36Sopenharmony_ci * @port: port to which the device is attached 63362306a36Sopenharmony_ci * @name: a name to refer to the device 63462306a36Sopenharmony_ci * @par_dev_cb: struct containing callbacks 63562306a36Sopenharmony_ci * @id: device number to be given to the device 63662306a36Sopenharmony_ci * 63762306a36Sopenharmony_ci * This function, called by parallel port device drivers, 63862306a36Sopenharmony_ci * declares that a device is connected to a port, and tells the 63962306a36Sopenharmony_ci * system all it needs to know. 64062306a36Sopenharmony_ci * 64162306a36Sopenharmony_ci * The struct pardev_cb contains pointer to callbacks. preemption 64262306a36Sopenharmony_ci * callback function, @preempt, is called when this device driver 64362306a36Sopenharmony_ci * has claimed access to the port but another device driver wants 64462306a36Sopenharmony_ci * to use it. It is given, @private, as its parameter, and should 64562306a36Sopenharmony_ci * return zero if it is willing for the system to release the port 64662306a36Sopenharmony_ci * to another driver on its behalf. If it wants to keep control of 64762306a36Sopenharmony_ci * the port it should return non-zero, and no action will be taken. 64862306a36Sopenharmony_ci * It is good manners for the driver to try to release the port at 64962306a36Sopenharmony_ci * the earliest opportunity after its preemption callback rejects a 65062306a36Sopenharmony_ci * preemption attempt. Note that if a preemption callback is happy 65162306a36Sopenharmony_ci * for preemption to go ahead, there is no need to release the 65262306a36Sopenharmony_ci * port; it is done automatically. This function may not block, as 65362306a36Sopenharmony_ci * it may be called from interrupt context. If the device driver 65462306a36Sopenharmony_ci * does not support preemption, @preempt can be %NULL. 65562306a36Sopenharmony_ci * 65662306a36Sopenharmony_ci * The wake-up ("kick") callback function, @wakeup, is called when 65762306a36Sopenharmony_ci * the port is available to be claimed for exclusive access; that 65862306a36Sopenharmony_ci * is, parport_claim() is guaranteed to succeed when called from 65962306a36Sopenharmony_ci * inside the wake-up callback function. If the driver wants to 66062306a36Sopenharmony_ci * claim the port it should do so; otherwise, it need not take 66162306a36Sopenharmony_ci * any action. This function may not block, as it may be called 66262306a36Sopenharmony_ci * from interrupt context. If the device driver does not want to 66362306a36Sopenharmony_ci * be explicitly invited to claim the port in this way, @wakeup can 66462306a36Sopenharmony_ci * be %NULL. 66562306a36Sopenharmony_ci * 66662306a36Sopenharmony_ci * The interrupt handler, @irq_func, is called when an interrupt 66762306a36Sopenharmony_ci * arrives from the parallel port. Note that if a device driver 66862306a36Sopenharmony_ci * wants to use interrupts it should use parport_enable_irq(), 66962306a36Sopenharmony_ci * and can also check the irq member of the parport structure 67062306a36Sopenharmony_ci * representing the port. 67162306a36Sopenharmony_ci * 67262306a36Sopenharmony_ci * The parallel port (lowlevel) driver is the one that has called 67362306a36Sopenharmony_ci * request_irq() and whose interrupt handler is called first. 67462306a36Sopenharmony_ci * This handler does whatever needs to be done to the hardware to 67562306a36Sopenharmony_ci * acknowledge the interrupt (for PC-style ports there is nothing 67662306a36Sopenharmony_ci * special to be done). It then tells the IEEE 1284 code about 67762306a36Sopenharmony_ci * the interrupt, which may involve reacting to an IEEE 1284 67862306a36Sopenharmony_ci * event depending on the current IEEE 1284 phase. After this, 67962306a36Sopenharmony_ci * it calls @irq_func. Needless to say, @irq_func will be called 68062306a36Sopenharmony_ci * from interrupt context, and may not block. 68162306a36Sopenharmony_ci * 68262306a36Sopenharmony_ci * The %PARPORT_DEV_EXCL flag is for preventing port sharing, and 68362306a36Sopenharmony_ci * so should only be used when sharing the port with other device 68462306a36Sopenharmony_ci * drivers is impossible and would lead to incorrect behaviour. 68562306a36Sopenharmony_ci * Use it sparingly! Normally, @flags will be zero. 68662306a36Sopenharmony_ci * 68762306a36Sopenharmony_ci * This function returns a pointer to a structure that represents 68862306a36Sopenharmony_ci * the device on the port, or %NULL if there is not enough memory 68962306a36Sopenharmony_ci * to allocate space for that structure. 69062306a36Sopenharmony_ci **/ 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistruct pardevice * 69362306a36Sopenharmony_ciparport_register_dev_model(struct parport *port, const char *name, 69462306a36Sopenharmony_ci const struct pardev_cb *par_dev_cb, int id) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci struct pardevice *par_dev; 69762306a36Sopenharmony_ci int ret; 69862306a36Sopenharmony_ci char *devname; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (port->physport->flags & PARPORT_FLAG_EXCL) { 70162306a36Sopenharmony_ci /* An exclusive device is registered. */ 70262306a36Sopenharmony_ci pr_err("%s: no more devices allowed\n", port->name); 70362306a36Sopenharmony_ci return NULL; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (par_dev_cb->flags & PARPORT_DEV_LURK) { 70762306a36Sopenharmony_ci if (!par_dev_cb->preempt || !par_dev_cb->wakeup) { 70862306a36Sopenharmony_ci pr_info("%s: refused to register lurking device (%s) without callbacks\n", 70962306a36Sopenharmony_ci port->name, name); 71062306a36Sopenharmony_ci return NULL; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (par_dev_cb->flags & PARPORT_DEV_EXCL) { 71562306a36Sopenharmony_ci if (port->physport->devices) { 71662306a36Sopenharmony_ci /* 71762306a36Sopenharmony_ci * If a device is already registered and this new 71862306a36Sopenharmony_ci * device wants exclusive access, then no need to 71962306a36Sopenharmony_ci * continue as we can not grant exclusive access to 72062306a36Sopenharmony_ci * this device. 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_ci pr_err("%s: cannot grant exclusive access for device %s\n", 72362306a36Sopenharmony_ci port->name, name); 72462306a36Sopenharmony_ci return NULL; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (!try_module_get(port->ops->owner)) 72962306a36Sopenharmony_ci return NULL; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci parport_get_port(port); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci par_dev = kzalloc(sizeof(*par_dev), GFP_KERNEL); 73462306a36Sopenharmony_ci if (!par_dev) 73562306a36Sopenharmony_ci goto err_put_port; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci par_dev->state = kzalloc(sizeof(*par_dev->state), GFP_KERNEL); 73862306a36Sopenharmony_ci if (!par_dev->state) 73962306a36Sopenharmony_ci goto err_put_par_dev; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci devname = kstrdup(name, GFP_KERNEL); 74262306a36Sopenharmony_ci if (!devname) 74362306a36Sopenharmony_ci goto err_free_par_dev; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci par_dev->name = devname; 74662306a36Sopenharmony_ci par_dev->port = port; 74762306a36Sopenharmony_ci par_dev->daisy = -1; 74862306a36Sopenharmony_ci par_dev->preempt = par_dev_cb->preempt; 74962306a36Sopenharmony_ci par_dev->wakeup = par_dev_cb->wakeup; 75062306a36Sopenharmony_ci par_dev->private = par_dev_cb->private; 75162306a36Sopenharmony_ci par_dev->flags = par_dev_cb->flags; 75262306a36Sopenharmony_ci par_dev->irq_func = par_dev_cb->irq_func; 75362306a36Sopenharmony_ci par_dev->waiting = 0; 75462306a36Sopenharmony_ci par_dev->timeout = 5 * HZ; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci par_dev->dev.parent = &port->bus_dev; 75762306a36Sopenharmony_ci par_dev->dev.bus = &parport_bus_type; 75862306a36Sopenharmony_ci ret = dev_set_name(&par_dev->dev, "%s.%d", devname, id); 75962306a36Sopenharmony_ci if (ret) 76062306a36Sopenharmony_ci goto err_free_devname; 76162306a36Sopenharmony_ci par_dev->dev.release = free_pardevice; 76262306a36Sopenharmony_ci par_dev->devmodel = true; 76362306a36Sopenharmony_ci ret = device_register(&par_dev->dev); 76462306a36Sopenharmony_ci if (ret) { 76562306a36Sopenharmony_ci kfree(par_dev->state); 76662306a36Sopenharmony_ci put_device(&par_dev->dev); 76762306a36Sopenharmony_ci goto err_put_port; 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci /* Chain this onto the list */ 77162306a36Sopenharmony_ci par_dev->prev = NULL; 77262306a36Sopenharmony_ci /* 77362306a36Sopenharmony_ci * This function must not run from an irq handler so we don' t need 77462306a36Sopenharmony_ci * to clear irq on the local CPU. -arca 77562306a36Sopenharmony_ci */ 77662306a36Sopenharmony_ci spin_lock(&port->physport->pardevice_lock); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci if (par_dev_cb->flags & PARPORT_DEV_EXCL) { 77962306a36Sopenharmony_ci if (port->physport->devices) { 78062306a36Sopenharmony_ci spin_unlock(&port->physport->pardevice_lock); 78162306a36Sopenharmony_ci pr_debug("%s: cannot grant exclusive access for device %s\n", 78262306a36Sopenharmony_ci port->name, name); 78362306a36Sopenharmony_ci kfree(par_dev->state); 78462306a36Sopenharmony_ci device_unregister(&par_dev->dev); 78562306a36Sopenharmony_ci goto err_put_port; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci port->flags |= PARPORT_FLAG_EXCL; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci par_dev->next = port->physport->devices; 79162306a36Sopenharmony_ci wmb(); /* 79262306a36Sopenharmony_ci * Make sure that tmp->next is written before it's 79362306a36Sopenharmony_ci * added to the list; see comments marked 'no locking 79462306a36Sopenharmony_ci * required' 79562306a36Sopenharmony_ci */ 79662306a36Sopenharmony_ci if (port->physport->devices) 79762306a36Sopenharmony_ci port->physport->devices->prev = par_dev; 79862306a36Sopenharmony_ci port->physport->devices = par_dev; 79962306a36Sopenharmony_ci spin_unlock(&port->physport->pardevice_lock); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci init_waitqueue_head(&par_dev->wait_q); 80262306a36Sopenharmony_ci par_dev->timeslice = parport_default_timeslice; 80362306a36Sopenharmony_ci par_dev->waitnext = NULL; 80462306a36Sopenharmony_ci par_dev->waitprev = NULL; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci /* 80762306a36Sopenharmony_ci * This has to be run as last thing since init_state may need other 80862306a36Sopenharmony_ci * pardevice fields. -arca 80962306a36Sopenharmony_ci */ 81062306a36Sopenharmony_ci port->ops->init_state(par_dev, par_dev->state); 81162306a36Sopenharmony_ci if (!test_and_set_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags)) { 81262306a36Sopenharmony_ci port->proc_device = par_dev; 81362306a36Sopenharmony_ci parport_device_proc_register(par_dev); 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci return par_dev; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cierr_free_devname: 81962306a36Sopenharmony_ci kfree(devname); 82062306a36Sopenharmony_cierr_free_par_dev: 82162306a36Sopenharmony_ci kfree(par_dev->state); 82262306a36Sopenharmony_cierr_put_par_dev: 82362306a36Sopenharmony_ci if (!par_dev->devmodel) 82462306a36Sopenharmony_ci kfree(par_dev); 82562306a36Sopenharmony_cierr_put_port: 82662306a36Sopenharmony_ci parport_put_port(port); 82762306a36Sopenharmony_ci module_put(port->ops->owner); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci return NULL; 83062306a36Sopenharmony_ci} 83162306a36Sopenharmony_ciEXPORT_SYMBOL(parport_register_dev_model); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci/** 83462306a36Sopenharmony_ci * parport_unregister_device - deregister a device on a parallel port 83562306a36Sopenharmony_ci * @dev: pointer to structure representing device 83662306a36Sopenharmony_ci * 83762306a36Sopenharmony_ci * This undoes the effect of parport_register_device(). 83862306a36Sopenharmony_ci **/ 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_civoid parport_unregister_device(struct pardevice *dev) 84162306a36Sopenharmony_ci{ 84262306a36Sopenharmony_ci struct parport *port; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci#ifdef PARPORT_PARANOID 84562306a36Sopenharmony_ci if (!dev) { 84662306a36Sopenharmony_ci pr_err("%s: passed NULL\n", __func__); 84762306a36Sopenharmony_ci return; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci#endif 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci port = dev->port->physport; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci if (port->proc_device == dev) { 85462306a36Sopenharmony_ci port->proc_device = NULL; 85562306a36Sopenharmony_ci clear_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags); 85662306a36Sopenharmony_ci parport_device_proc_unregister(dev); 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci if (port->cad == dev) { 86062306a36Sopenharmony_ci printk(KERN_DEBUG "%s: %s forgot to release port\n", 86162306a36Sopenharmony_ci port->name, dev->name); 86262306a36Sopenharmony_ci parport_release(dev); 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci spin_lock(&port->pardevice_lock); 86662306a36Sopenharmony_ci if (dev->next) 86762306a36Sopenharmony_ci dev->next->prev = dev->prev; 86862306a36Sopenharmony_ci if (dev->prev) 86962306a36Sopenharmony_ci dev->prev->next = dev->next; 87062306a36Sopenharmony_ci else 87162306a36Sopenharmony_ci port->devices = dev->next; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci if (dev->flags & PARPORT_DEV_EXCL) 87462306a36Sopenharmony_ci port->flags &= ~PARPORT_FLAG_EXCL; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci spin_unlock(&port->pardevice_lock); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci /* 87962306a36Sopenharmony_ci * Make sure we haven't left any pointers around in the wait 88062306a36Sopenharmony_ci * list. 88162306a36Sopenharmony_ci */ 88262306a36Sopenharmony_ci spin_lock_irq(&port->waitlist_lock); 88362306a36Sopenharmony_ci if (dev->waitprev || dev->waitnext || port->waithead == dev) { 88462306a36Sopenharmony_ci if (dev->waitprev) 88562306a36Sopenharmony_ci dev->waitprev->waitnext = dev->waitnext; 88662306a36Sopenharmony_ci else 88762306a36Sopenharmony_ci port->waithead = dev->waitnext; 88862306a36Sopenharmony_ci if (dev->waitnext) 88962306a36Sopenharmony_ci dev->waitnext->waitprev = dev->waitprev; 89062306a36Sopenharmony_ci else 89162306a36Sopenharmony_ci port->waittail = dev->waitprev; 89262306a36Sopenharmony_ci } 89362306a36Sopenharmony_ci spin_unlock_irq(&port->waitlist_lock); 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci kfree(dev->state); 89662306a36Sopenharmony_ci device_unregister(&dev->dev); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci module_put(port->ops->owner); 89962306a36Sopenharmony_ci parport_put_port(port); 90062306a36Sopenharmony_ci} 90162306a36Sopenharmony_ciEXPORT_SYMBOL(parport_unregister_device); 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci/** 90462306a36Sopenharmony_ci * parport_find_number - find a parallel port by number 90562306a36Sopenharmony_ci * @number: parallel port number 90662306a36Sopenharmony_ci * 90762306a36Sopenharmony_ci * This returns the parallel port with the specified number, or 90862306a36Sopenharmony_ci * %NULL if there is none. 90962306a36Sopenharmony_ci * 91062306a36Sopenharmony_ci * There is an implicit parport_get_port() done already; to throw 91162306a36Sopenharmony_ci * away the reference to the port that parport_find_number() 91262306a36Sopenharmony_ci * gives you, use parport_put_port(). 91362306a36Sopenharmony_ci */ 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cistruct parport *parport_find_number(int number) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci struct parport *port, *result = NULL; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (list_empty(&portlist)) 92062306a36Sopenharmony_ci get_lowlevel_driver(); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci spin_lock(&parportlist_lock); 92362306a36Sopenharmony_ci list_for_each_entry(port, &portlist, list) { 92462306a36Sopenharmony_ci if (port->number == number) { 92562306a36Sopenharmony_ci result = parport_get_port(port); 92662306a36Sopenharmony_ci break; 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci } 92962306a36Sopenharmony_ci spin_unlock(&parportlist_lock); 93062306a36Sopenharmony_ci return result; 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ciEXPORT_SYMBOL(parport_find_number); 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci/** 93562306a36Sopenharmony_ci * parport_find_base - find a parallel port by base address 93662306a36Sopenharmony_ci * @base: base I/O address 93762306a36Sopenharmony_ci * 93862306a36Sopenharmony_ci * This returns the parallel port with the specified base 93962306a36Sopenharmony_ci * address, or %NULL if there is none. 94062306a36Sopenharmony_ci * 94162306a36Sopenharmony_ci * There is an implicit parport_get_port() done already; to throw 94262306a36Sopenharmony_ci * away the reference to the port that parport_find_base() 94362306a36Sopenharmony_ci * gives you, use parport_put_port(). 94462306a36Sopenharmony_ci */ 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_cistruct parport *parport_find_base(unsigned long base) 94762306a36Sopenharmony_ci{ 94862306a36Sopenharmony_ci struct parport *port, *result = NULL; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci if (list_empty(&portlist)) 95162306a36Sopenharmony_ci get_lowlevel_driver(); 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci spin_lock(&parportlist_lock); 95462306a36Sopenharmony_ci list_for_each_entry(port, &portlist, list) { 95562306a36Sopenharmony_ci if (port->base == base) { 95662306a36Sopenharmony_ci result = parport_get_port(port); 95762306a36Sopenharmony_ci break; 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci } 96062306a36Sopenharmony_ci spin_unlock(&parportlist_lock); 96162306a36Sopenharmony_ci return result; 96262306a36Sopenharmony_ci} 96362306a36Sopenharmony_ciEXPORT_SYMBOL(parport_find_base); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci/** 96662306a36Sopenharmony_ci * parport_claim - claim access to a parallel port device 96762306a36Sopenharmony_ci * @dev: pointer to structure representing a device on the port 96862306a36Sopenharmony_ci * 96962306a36Sopenharmony_ci * This function will not block and so can be used from interrupt 97062306a36Sopenharmony_ci * context. If parport_claim() succeeds in claiming access to 97162306a36Sopenharmony_ci * the port it returns zero and the port is available to use. It 97262306a36Sopenharmony_ci * may fail (returning non-zero) if the port is in use by another 97362306a36Sopenharmony_ci * driver and that driver is not willing to relinquish control of 97462306a36Sopenharmony_ci * the port. 97562306a36Sopenharmony_ci **/ 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ciint parport_claim(struct pardevice *dev) 97862306a36Sopenharmony_ci{ 97962306a36Sopenharmony_ci struct pardevice *oldcad; 98062306a36Sopenharmony_ci struct parport *port = dev->port->physport; 98162306a36Sopenharmony_ci unsigned long flags; 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci if (port->cad == dev) { 98462306a36Sopenharmony_ci pr_info("%s: %s already owner\n", dev->port->name, dev->name); 98562306a36Sopenharmony_ci return 0; 98662306a36Sopenharmony_ci } 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci /* Preempt any current device */ 98962306a36Sopenharmony_ci write_lock_irqsave(&port->cad_lock, flags); 99062306a36Sopenharmony_ci oldcad = port->cad; 99162306a36Sopenharmony_ci if (oldcad) { 99262306a36Sopenharmony_ci if (oldcad->preempt) { 99362306a36Sopenharmony_ci if (oldcad->preempt(oldcad->private)) 99462306a36Sopenharmony_ci goto blocked; 99562306a36Sopenharmony_ci port->ops->save_state(port, dev->state); 99662306a36Sopenharmony_ci } else 99762306a36Sopenharmony_ci goto blocked; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci if (port->cad != oldcad) { 100062306a36Sopenharmony_ci /* 100162306a36Sopenharmony_ci * I think we'll actually deadlock rather than 100262306a36Sopenharmony_ci * get here, but just in case.. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_ci pr_warn("%s: %s released port when preempted!\n", 100562306a36Sopenharmony_ci port->name, oldcad->name); 100662306a36Sopenharmony_ci if (port->cad) 100762306a36Sopenharmony_ci goto blocked; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci } 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* Can't fail from now on, so mark ourselves as no longer waiting. */ 101262306a36Sopenharmony_ci if (dev->waiting & 1) { 101362306a36Sopenharmony_ci dev->waiting = 0; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci /* Take ourselves out of the wait list again. */ 101662306a36Sopenharmony_ci spin_lock_irq(&port->waitlist_lock); 101762306a36Sopenharmony_ci if (dev->waitprev) 101862306a36Sopenharmony_ci dev->waitprev->waitnext = dev->waitnext; 101962306a36Sopenharmony_ci else 102062306a36Sopenharmony_ci port->waithead = dev->waitnext; 102162306a36Sopenharmony_ci if (dev->waitnext) 102262306a36Sopenharmony_ci dev->waitnext->waitprev = dev->waitprev; 102362306a36Sopenharmony_ci else 102462306a36Sopenharmony_ci port->waittail = dev->waitprev; 102562306a36Sopenharmony_ci spin_unlock_irq(&port->waitlist_lock); 102662306a36Sopenharmony_ci dev->waitprev = dev->waitnext = NULL; 102762306a36Sopenharmony_ci } 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci /* Now we do the change of devices */ 103062306a36Sopenharmony_ci port->cad = dev; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci#ifdef CONFIG_PARPORT_1284 103362306a36Sopenharmony_ci /* If it's a mux port, select it. */ 103462306a36Sopenharmony_ci if (dev->port->muxport >= 0) { 103562306a36Sopenharmony_ci /* FIXME */ 103662306a36Sopenharmony_ci port->muxsel = dev->port->muxport; 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci /* If it's a daisy chain device, select it. */ 104062306a36Sopenharmony_ci if (dev->daisy >= 0) { 104162306a36Sopenharmony_ci /* This could be lazier. */ 104262306a36Sopenharmony_ci if (!parport_daisy_select(port, dev->daisy, 104362306a36Sopenharmony_ci IEEE1284_MODE_COMPAT)) 104462306a36Sopenharmony_ci port->daisy = dev->daisy; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci#endif /* IEEE1284.3 support */ 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci /* Restore control registers */ 104962306a36Sopenharmony_ci port->ops->restore_state(port, dev->state); 105062306a36Sopenharmony_ci write_unlock_irqrestore(&port->cad_lock, flags); 105162306a36Sopenharmony_ci dev->time = jiffies; 105262306a36Sopenharmony_ci return 0; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ciblocked: 105562306a36Sopenharmony_ci /* 105662306a36Sopenharmony_ci * If this is the first time we tried to claim the port, register an 105762306a36Sopenharmony_ci * interest. This is only allowed for devices sleeping in 105862306a36Sopenharmony_ci * parport_claim_or_block(), or those with a wakeup function. 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci /* The cad_lock is still held for writing here */ 106262306a36Sopenharmony_ci if (dev->waiting & 2 || dev->wakeup) { 106362306a36Sopenharmony_ci spin_lock(&port->waitlist_lock); 106462306a36Sopenharmony_ci if (test_and_set_bit(0, &dev->waiting) == 0) { 106562306a36Sopenharmony_ci /* First add ourselves to the end of the wait list. */ 106662306a36Sopenharmony_ci dev->waitnext = NULL; 106762306a36Sopenharmony_ci dev->waitprev = port->waittail; 106862306a36Sopenharmony_ci if (port->waittail) { 106962306a36Sopenharmony_ci port->waittail->waitnext = dev; 107062306a36Sopenharmony_ci port->waittail = dev; 107162306a36Sopenharmony_ci } else 107262306a36Sopenharmony_ci port->waithead = port->waittail = dev; 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci spin_unlock(&port->waitlist_lock); 107562306a36Sopenharmony_ci } 107662306a36Sopenharmony_ci write_unlock_irqrestore(&port->cad_lock, flags); 107762306a36Sopenharmony_ci return -EAGAIN; 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ciEXPORT_SYMBOL(parport_claim); 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci/** 108262306a36Sopenharmony_ci * parport_claim_or_block - claim access to a parallel port device 108362306a36Sopenharmony_ci * @dev: pointer to structure representing a device on the port 108462306a36Sopenharmony_ci * 108562306a36Sopenharmony_ci * This behaves like parport_claim(), but will block if necessary 108662306a36Sopenharmony_ci * to wait for the port to be free. A return value of 1 108762306a36Sopenharmony_ci * indicates that it slept; 0 means that it succeeded without 108862306a36Sopenharmony_ci * needing to sleep. A negative error code indicates failure. 108962306a36Sopenharmony_ci **/ 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ciint parport_claim_or_block(struct pardevice *dev) 109262306a36Sopenharmony_ci{ 109362306a36Sopenharmony_ci int r; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci /* 109662306a36Sopenharmony_ci * Signal to parport_claim() that we can wait even without a 109762306a36Sopenharmony_ci * wakeup function. 109862306a36Sopenharmony_ci */ 109962306a36Sopenharmony_ci dev->waiting = 2; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* Try to claim the port. If this fails, we need to sleep. */ 110262306a36Sopenharmony_ci r = parport_claim(dev); 110362306a36Sopenharmony_ci if (r == -EAGAIN) { 110462306a36Sopenharmony_ci#ifdef PARPORT_DEBUG_SHARING 110562306a36Sopenharmony_ci printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", 110662306a36Sopenharmony_ci dev->name); 110762306a36Sopenharmony_ci#endif 110862306a36Sopenharmony_ci /* 110962306a36Sopenharmony_ci * FIXME!!! Use the proper locking for dev->waiting, 111062306a36Sopenharmony_ci * and make this use the "wait_event_interruptible()" 111162306a36Sopenharmony_ci * interfaces. The cli/sti that used to be here 111262306a36Sopenharmony_ci * did nothing. 111362306a36Sopenharmony_ci * 111462306a36Sopenharmony_ci * See also parport_release() 111562306a36Sopenharmony_ci */ 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci /* 111862306a36Sopenharmony_ci * If dev->waiting is clear now, an interrupt 111962306a36Sopenharmony_ci * gave us the port and we would deadlock if we slept. 112062306a36Sopenharmony_ci */ 112162306a36Sopenharmony_ci if (dev->waiting) { 112262306a36Sopenharmony_ci wait_event_interruptible(dev->wait_q, 112362306a36Sopenharmony_ci !dev->waiting); 112462306a36Sopenharmony_ci if (signal_pending(current)) 112562306a36Sopenharmony_ci return -EINTR; 112662306a36Sopenharmony_ci r = 1; 112762306a36Sopenharmony_ci } else { 112862306a36Sopenharmony_ci r = 0; 112962306a36Sopenharmony_ci#ifdef PARPORT_DEBUG_SHARING 113062306a36Sopenharmony_ci printk(KERN_DEBUG "%s: didn't sleep in parport_claim_or_block()\n", 113162306a36Sopenharmony_ci dev->name); 113262306a36Sopenharmony_ci#endif 113362306a36Sopenharmony_ci } 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci#ifdef PARPORT_DEBUG_SHARING 113662306a36Sopenharmony_ci if (dev->port->physport->cad != dev) 113762306a36Sopenharmony_ci printk(KERN_DEBUG "%s: exiting parport_claim_or_block but %s owns port!\n", 113862306a36Sopenharmony_ci dev->name, dev->port->physport->cad ? 113962306a36Sopenharmony_ci dev->port->physport->cad->name : "nobody"); 114062306a36Sopenharmony_ci#endif 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci dev->waiting = 0; 114362306a36Sopenharmony_ci return r; 114462306a36Sopenharmony_ci} 114562306a36Sopenharmony_ciEXPORT_SYMBOL(parport_claim_or_block); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci/** 114862306a36Sopenharmony_ci * parport_release - give up access to a parallel port device 114962306a36Sopenharmony_ci * @dev: pointer to structure representing parallel port device 115062306a36Sopenharmony_ci * 115162306a36Sopenharmony_ci * This function cannot fail, but it should not be called without 115262306a36Sopenharmony_ci * the port claimed. Similarly, if the port is already claimed 115362306a36Sopenharmony_ci * you should not try claiming it again. 115462306a36Sopenharmony_ci **/ 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_civoid parport_release(struct pardevice *dev) 115762306a36Sopenharmony_ci{ 115862306a36Sopenharmony_ci struct parport *port = dev->port->physport; 115962306a36Sopenharmony_ci struct pardevice *pd; 116062306a36Sopenharmony_ci unsigned long flags; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci /* Make sure that dev is the current device */ 116362306a36Sopenharmony_ci write_lock_irqsave(&port->cad_lock, flags); 116462306a36Sopenharmony_ci if (port->cad != dev) { 116562306a36Sopenharmony_ci write_unlock_irqrestore(&port->cad_lock, flags); 116662306a36Sopenharmony_ci pr_warn("%s: %s tried to release parport when not owner\n", 116762306a36Sopenharmony_ci port->name, dev->name); 116862306a36Sopenharmony_ci return; 116962306a36Sopenharmony_ci } 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci#ifdef CONFIG_PARPORT_1284 117262306a36Sopenharmony_ci /* If this is on a mux port, deselect it. */ 117362306a36Sopenharmony_ci if (dev->port->muxport >= 0) { 117462306a36Sopenharmony_ci /* FIXME */ 117562306a36Sopenharmony_ci port->muxsel = -1; 117662306a36Sopenharmony_ci } 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci /* If this is a daisy device, deselect it. */ 117962306a36Sopenharmony_ci if (dev->daisy >= 0) { 118062306a36Sopenharmony_ci parport_daisy_deselect_all(port); 118162306a36Sopenharmony_ci port->daisy = -1; 118262306a36Sopenharmony_ci } 118362306a36Sopenharmony_ci#endif 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci port->cad = NULL; 118662306a36Sopenharmony_ci write_unlock_irqrestore(&port->cad_lock, flags); 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci /* Save control registers */ 118962306a36Sopenharmony_ci port->ops->save_state(port, dev->state); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci /* 119262306a36Sopenharmony_ci * If anybody is waiting, find out who's been there longest and 119362306a36Sopenharmony_ci * then wake them up. (Note: no locking required) 119462306a36Sopenharmony_ci */ 119562306a36Sopenharmony_ci /* !!! LOCKING IS NEEDED HERE */ 119662306a36Sopenharmony_ci for (pd = port->waithead; pd; pd = pd->waitnext) { 119762306a36Sopenharmony_ci if (pd->waiting & 2) { /* sleeping in claim_or_block */ 119862306a36Sopenharmony_ci parport_claim(pd); 119962306a36Sopenharmony_ci if (waitqueue_active(&pd->wait_q)) 120062306a36Sopenharmony_ci wake_up_interruptible(&pd->wait_q); 120162306a36Sopenharmony_ci return; 120262306a36Sopenharmony_ci } else if (pd->wakeup) { 120362306a36Sopenharmony_ci pd->wakeup(pd->private); 120462306a36Sopenharmony_ci if (dev->port->cad) /* racy but no matter */ 120562306a36Sopenharmony_ci return; 120662306a36Sopenharmony_ci } else { 120762306a36Sopenharmony_ci pr_err("%s: don't know how to wake %s\n", 120862306a36Sopenharmony_ci port->name, pd->name); 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci /* 121362306a36Sopenharmony_ci * Nobody was waiting, so walk the list to see if anyone is 121462306a36Sopenharmony_ci * interested in being woken up. (Note: no locking required) 121562306a36Sopenharmony_ci */ 121662306a36Sopenharmony_ci /* !!! LOCKING IS NEEDED HERE */ 121762306a36Sopenharmony_ci for (pd = port->devices; !port->cad && pd; pd = pd->next) { 121862306a36Sopenharmony_ci if (pd->wakeup && pd != dev) 121962306a36Sopenharmony_ci pd->wakeup(pd->private); 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci} 122262306a36Sopenharmony_ciEXPORT_SYMBOL(parport_release); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ciirqreturn_t parport_irq_handler(int irq, void *dev_id) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci struct parport *port = dev_id; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci parport_generic_irq(port); 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci return IRQ_HANDLED; 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ciEXPORT_SYMBOL(parport_irq_handler); 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1235