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(®istration_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(®istration_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(®istration_lock); 3428c2ecf20Sopenharmony_ci bus_for_each_dev(&parport_bus_type, NULL, drv, port_detach); 3438c2ecf20Sopenharmony_ci driver_unregister(&drv->driver); 3448c2ecf20Sopenharmony_ci mutex_unlock(®istration_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(®istration_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(®istration_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(®istration_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(®istration_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