Commit a936e3de authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/libata-2.5

into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents cdf650f2 460070ce
......@@ -862,10 +862,9 @@ static void lp_detach (struct parport *port)
}
static struct parport_driver lp_driver = {
"lp",
lp_attach,
lp_detach,
NULL
.name = "lp",
.attach = lp_attach,
.detach = lp_detach,
};
int __init lp_init (void)
......
......@@ -463,10 +463,9 @@ tipar_detach(struct parport *port)
}
static struct parport_driver tipar_driver = {
"tipar",
tipar_attach,
tipar_detach,
NULL
.name = "tipar",
.attach = tipar_attach,
.detach = tipar_detach,
};
int __init
......
......@@ -818,10 +818,9 @@ static void cq_detach(struct parport *port)
}
static struct parport_driver cqcam_driver = {
"cqcam",
cq_attach,
cq_detach,
NULL
.name = "cqcam",
.attach = cq_attach,
.detach = cq_detach,
};
static int __init cqcam_init (void)
......
......@@ -803,10 +803,9 @@ static void cpia_pp_attach (struct parport *port)
}
static struct parport_driver cpia_pp_driver = {
"cpia_pp",
cpia_pp_attach,
cpia_pp_detach,
NULL
.name = "cpia_pp",
.attach = cpia_pp_attach,
.detach = cpia_pp_detach,
};
int cpia_pp_init(void)
......@@ -853,11 +852,6 @@ int init_module(void)
}
}
}
#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE)
if(parport_enumerate() && !parport_enumerate()->probe_info.model) {
request_module("parport_probe");
}
#endif
return cpia_pp_init();
}
......
......@@ -959,10 +959,9 @@ static void w9966_detach(struct parport *port)
static struct parport_driver w9966_ppd = {
W9966_DRIVERNAME,
w9966_attach,
w9966_detach,
NULL
.name = W9966_DRIVERNAME,
.attach = w9966_attach,
.detach = w9966_detach,
};
// Module entry point
......
......@@ -2,7 +2,7 @@
# Makefile for the kernel Parallel port device drivers.
#
parport-objs := share.o ieee1284.o ieee1284_ops.o init.o procfs.o
parport-objs := share.o ieee1284.o ieee1284_ops.o procfs.o
ifeq ($(CONFIG_PARPORT_1284),y)
parport-objs += daisy.o probe.o
......
......@@ -19,6 +19,7 @@
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/parport.h>
#include <linux/delay.h>
#include <linux/sched.h>
......@@ -79,6 +80,7 @@ static struct parport *clone_parport (struct parport *real, int muxport)
extra->portnum = real->portnum;
extra->physport = real;
extra->muxport = muxport;
real->slaves[muxport-1] = extra;
}
return extra;
......@@ -93,7 +95,9 @@ int parport_daisy_init (struct parport *port)
static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
int num_ports;
int i;
int last_try = 0;
again:
/* Because this is called before any other devices exist,
* we don't have to claim exclusive access. */
......@@ -126,7 +130,7 @@ int parport_daisy_init (struct parport *port)
/* Analyse that port too. We won't recurse
forever because of the 'port->muxport < 0'
test above. */
parport_announce_port (extra);
parport_daisy_init(extra);
}
}
......@@ -148,6 +152,21 @@ int parport_daisy_init (struct parport *port)
kfree (deviceid);
}
if (!detected && !last_try) {
/* No devices were detected. Perhaps they are in some
funny state; let's try to reset them and see if
they wake up. */
parport_daisy_fini (port);
parport_write_control (port, PARPORT_CONTROL_SELECT);
udelay (50);
parport_write_control (port,
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT);
udelay (50);
last_try = 1;
goto again;
}
return detected;
}
......@@ -634,3 +653,13 @@ int parport_find_class (parport_device_class cls, int from)
spin_unlock(&topology_lock);
return res;
}
EXPORT_SYMBOL(parport_open);
EXPORT_SYMBOL(parport_close);
EXPORT_SYMBOL(parport_device_num);
EXPORT_SYMBOL(parport_device_coords);
EXPORT_SYMBOL(parport_daisy_deselect_all);
EXPORT_SYMBOL(parport_daisy_select);
EXPORT_SYMBOL(parport_daisy_init);
EXPORT_SYMBOL(parport_find_device);
EXPORT_SYMBOL(parport_find_class);
......@@ -17,6 +17,7 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/threads.h>
#include <linux/parport.h>
#include <linux/delay.h>
......@@ -806,3 +807,15 @@ long parport_set_timeout (struct pardevice *dev, long inactivity)
return old;
}
/* Exported symbols for modules. */
EXPORT_SYMBOL(parport_negotiate);
EXPORT_SYMBOL(parport_write);
EXPORT_SYMBOL(parport_read);
EXPORT_SYMBOL(parport_ieee1284_wakeup);
EXPORT_SYMBOL(parport_wait_peripheral);
EXPORT_SYMBOL(parport_poll_peripheral);
EXPORT_SYMBOL(parport_wait_event);
EXPORT_SYMBOL(parport_set_timeout);
EXPORT_SYMBOL(parport_ieee1284_interrupt);
......@@ -15,6 +15,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/parport.h>
#include <linux/delay.h>
#include <linux/sched.h>
......@@ -908,4 +909,13 @@ size_t parport_ieee1284_epp_read_addr (struct parport *port,
return ret;
}
EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
EXPORT_SYMBOL(parport_ieee1284_write_compat);
EXPORT_SYMBOL(parport_ieee1284_read_nibble);
EXPORT_SYMBOL(parport_ieee1284_read_byte);
EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
/* Parallel-port initialisation code.
*
* Authors: David Campbell <campbell@torque.net>
* Tim Waugh <tim@cyberelk.demon.co.uk>
* Jose Renau <renau@acm.org>
*
* based on work by Grant Guenther <grant@torque.net>
* and Philip Blundell <Philip.Blundell@pobox.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/threads.h>
#include <linux/string.h>
#include <linux/parport.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#ifndef MODULE
static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
#ifdef CONFIG_PARPORT_PC
static int io_hi[PARPORT_MAX+1] __initdata =
{ [0 ... PARPORT_MAX] = PARPORT_IOHI_AUTO };
#endif
static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma);
extern int parport_sunbpp_init(void);
extern int parport_amiga_init(void);
extern int parport_mfc3_init(void);
extern int parport_atari_init(void);
static int parport_setup_ptr __initdata = 0;
/*
* Acceptable parameters:
*
* parport=0
* parport=auto
* parport=0xBASE[,IRQ[,DMA]]
*
* IRQ/DMA may be numeric or 'auto' or 'none'
*/
static int __init parport_setup (char *str)
{
char *endptr;
char *sep;
int val;
if (!str || !*str || (*str == '0' && !*(str+1))) {
/* Disable parport if "parport=0" in cmdline */
io[0] = PARPORT_DISABLE;
return 1;
}
if (!strncmp (str, "auto", 4)) {
irq[0] = PARPORT_IRQ_AUTO;
dma[0] = PARPORT_DMA_AUTO;
return 1;
}
val = simple_strtoul (str, &endptr, 0);
if (endptr == str) {
printk (KERN_WARNING "parport=%s not understood\n", str);
return 1;
}
if (parport_setup_ptr == PARPORT_MAX) {
printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
return 1;
}
io[parport_setup_ptr] = val;
irq[parport_setup_ptr] = PARPORT_IRQ_NONE;
dma[parport_setup_ptr] = PARPORT_DMA_NONE;
sep = strchr (str, ',');
if (sep++) {
if (!strncmp (sep, "auto", 4))
irq[parport_setup_ptr] = PARPORT_IRQ_AUTO;
else if (strncmp (sep, "none", 4)) {
val = simple_strtoul (sep, &endptr, 0);
if (endptr == sep) {
printk (KERN_WARNING
"parport=%s: irq not understood\n",
str);
return 1;
}
irq[parport_setup_ptr] = val;
}
}
sep = strchr (sep, ',');
if (sep++) {
if (!strncmp (sep, "auto", 4))
dma[parport_setup_ptr] = PARPORT_DMA_AUTO;
else if (!strncmp (sep, "nofifo", 6))
dma[parport_setup_ptr] = PARPORT_DMA_NOFIFO;
else if (strncmp (sep, "none", 4)) {
val = simple_strtoul (sep, &endptr, 0);
if (endptr == sep) {
printk (KERN_WARNING
"parport=%s: dma not understood\n",
str);
return 1;
}
dma[parport_setup_ptr] = val;
}
}
parport_setup_ptr++;
return 1;
}
__setup ("parport=", parport_setup);
#endif
#ifdef MODULE
int init_module(void)
{
#ifdef CONFIG_SYSCTL
parport_default_proc_register ();
#endif
return 0;
}
void cleanup_module(void)
{
#ifdef CONFIG_SYSCTL
parport_default_proc_unregister ();
#endif
}
#else
int __init parport_init (void)
{
if (io[0] == PARPORT_DISABLE)
return 1;
#ifdef CONFIG_SYSCTL
parport_default_proc_register ();
#endif
#ifdef CONFIG_PARPORT_PC
parport_pc_init(io, io_hi, irq, dma);
#endif
#ifdef CONFIG_PARPORT_AMIGA
parport_amiga_init();
#endif
#ifdef CONFIG_PARPORT_MFC3
parport_mfc3_init();
#endif
#ifdef CONFIG_PARPORT_ATARI
parport_atari_init();
#endif
#ifdef CONFIG_PARPORT_ARC
parport_arc_init();
#endif
#ifdef CONFIG_PARPORT_SUNBPP
parport_sunbpp_init();
#endif
return 0;
}
__initcall(parport_init);
#endif
/* Exported symbols for modules. */
EXPORT_SYMBOL(parport_claim);
EXPORT_SYMBOL(parport_claim_or_block);
EXPORT_SYMBOL(parport_release);
EXPORT_SYMBOL(parport_register_port);
EXPORT_SYMBOL(parport_announce_port);
EXPORT_SYMBOL(parport_unregister_port);
EXPORT_SYMBOL(parport_register_driver);
EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number);
EXPORT_SYMBOL(parport_find_base);
EXPORT_SYMBOL(parport_negotiate);
EXPORT_SYMBOL(parport_write);
EXPORT_SYMBOL(parport_read);
EXPORT_SYMBOL(parport_ieee1284_wakeup);
EXPORT_SYMBOL(parport_wait_peripheral);
EXPORT_SYMBOL(parport_poll_peripheral);
EXPORT_SYMBOL(parport_wait_event);
EXPORT_SYMBOL(parport_set_timeout);
EXPORT_SYMBOL(parport_ieee1284_interrupt);
EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
EXPORT_SYMBOL(parport_ieee1284_write_compat);
EXPORT_SYMBOL(parport_ieee1284_read_nibble);
EXPORT_SYMBOL(parport_ieee1284_read_byte);
EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
EXPORT_SYMBOL(parport_proc_register);
EXPORT_SYMBOL(parport_proc_unregister);
EXPORT_SYMBOL(parport_device_proc_register);
EXPORT_SYMBOL(parport_device_proc_unregister);
EXPORT_SYMBOL(parport_default_proc_register);
EXPORT_SYMBOL(parport_default_proc_unregister);
EXPORT_SYMBOL(parport_parse_irqs);
EXPORT_SYMBOL(parport_parse_dmas);
#ifdef CONFIG_PARPORT_1284
EXPORT_SYMBOL(parport_open);
EXPORT_SYMBOL(parport_close);
EXPORT_SYMBOL(parport_device_id);
EXPORT_SYMBOL(parport_device_num);
EXPORT_SYMBOL(parport_device_coords);
EXPORT_SYMBOL(parport_daisy_deselect_all);
EXPORT_SYMBOL(parport_daisy_select);
EXPORT_SYMBOL(parport_daisy_init);
EXPORT_SYMBOL(parport_find_device);
EXPORT_SYMBOL(parport_find_class);
#endif
......@@ -234,7 +234,7 @@ static struct parport_operations pp_amiga_ops = {
/* ----------- Initialisation code --------------------------------- */
int __init parport_amiga_init(void)
static int __init parport_amiga_init(void)
{
struct parport *p;
int err;
......@@ -262,26 +262,24 @@ int __init parport_amiga_init(void)
this_port = p;
printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
/* XXX: set operating mode */
parport_proc_register(p);
parport_announce_port(p);
return 0;
out_irq:
parport_unregister_port(p);
parport_put_port(p);
out_port:
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
out_mem:
return err;
}
void __exit parport_amiga_exit(void)
static void __exit parport_amiga_exit(void)
{
parport_remove_port(this_port);
if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
parport_proc_unregister(this_port);
parport_unregister_port(this_port);
parport_put_port(this_port);
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
}
......
......@@ -104,7 +104,7 @@ static struct parport_operations parport_arc_ops =
/* --- Initialisation code -------------------------------- */
int parport_arc_init(void)
static int parport_arc_init(void)
{
/* Archimedes hardware provides only one port, at a fixed address */
struct parport *p;
......@@ -129,10 +129,11 @@ int parport_arc_init(void)
printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
p->irq);
parport_proc_register(p);
/* Tell the high-level drivers about the port. */
parport_announce_port (p);
return 1;
}
module_init(parport_arc_init)
......@@ -185,8 +185,7 @@ static struct parport_operations parport_atari_ops = {
};
int __init
parport_atari_init(void)
static int __init parport_atari_init(void)
{
struct parport *p;
unsigned long flags;
......@@ -208,43 +207,34 @@ parport_atari_init(void)
IRQ_MFP_BUSY, PARPORT_DMA_NONE,
&parport_atari_ops);
if (!p)
return 0;
return -ENODEV;
if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
IRQ_TYPE_SLOW, p->name, p)) {
parport_unregister_port (p);
return 0;
parport_put_port (p);
return -ENODEV;
}
this_port = p;
printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
parport_proc_register(p);
parport_announce_port (p);
return 1;
return 0;
}
return 0;
return -ENODEV;
}
#ifdef MODULE
static void __exit parport_atari_exit(void)
{
parport_remove_port(this_port);
if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_MFP_BUSY, this_port);
parport_put_port(this_port);
}
MODULE_AUTHOR("Andreas Schwab");
MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
MODULE_LICENSE("GPL");
int
init_module(void)
{
return parport_atari_init() ? 0 : -ENODEV;
}
void
cleanup_module(void)
{
if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_MFP_BUSY, this_port);
parport_proc_unregister(this_port);
parport_unregister_port(this_port);
}
#endif
module_init(parport_atari_init)
module_exit(parport_atari_exit)
......@@ -412,7 +412,6 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
}
#undef printmode
printk("]\n");
parport_proc_register(p);
if (p->irq != PARPORT_IRQ_NONE) {
if (request_irq (p->irq, parport_gsc_interrupt,
......@@ -483,17 +482,17 @@ static void __devexit parport_remove_chip(struct parisc_device *dev)
if (p) {
struct parport_gsc_private *priv = p->private_data;
struct parport_operations *ops = p->ops;
parport_remove_port(p);
if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p);
parport_proc_unregister(p);
if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE,
priv->dma_buf,
priv->dma_handle);
kfree (p->private_data);
parport_unregister_port(p);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
}
}
......
......@@ -320,7 +320,7 @@ static struct parport_operations pp_mfc3_ops = {
/* ----------- Initialisation code --------------------------------- */
int __init parport_mfc3_init(void)
static int __init parport_mfc3_init(void)
{
struct parport *p;
int pias = 0;
......@@ -360,7 +360,6 @@ int __init parport_mfc3_init(void)
this_port[pias++] = p;
printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
/* XXX: set operating mode */
parport_proc_register(p);
p->private_data = (void *)piabase;
parport_announce_port (p);
......@@ -370,7 +369,7 @@ int __init parport_mfc3_init(void)
continue;
out_irq:
parport_unregister_port(p);
parport_put_port(p);
out_port:
release_mem_region(piabase, sizeof(struct pia));
}
......@@ -378,20 +377,20 @@ int __init parport_mfc3_init(void)
return pias ? 0 : -ENODEV;
}
void __exit parport_mfc3_exit(void)
static void __exit parport_mfc3_exit(void)
{
int i;
for (i = 0; i < MAX_MFC; i++) {
if (!this_port[i])
continue;
parport_remove_port(this_port[i]);
if (!this_port[i]->irq != PARPORT_IRQ_NONE) {
if (--use_cnt == 0)
free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
}
parport_proc_unregister(this_port[i]);
parport_unregister_port(this_port[i]);
release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia));
parport_put_port(this_port[i]);
}
}
......@@ -403,4 +402,3 @@ MODULE_LICENSE("GPL");
module_init(parport_mfc3_init)
module_exit(parport_mfc3_exit)
......@@ -2107,6 +2107,9 @@ static int __devinit parport_dma_probe (struct parport *p)
/* --- Initialisation code -------------------------------- */
static LIST_HEAD(ports_list);
static spinlock_t ports_lock = SPIN_LOCK_UNLOCKED;
struct parport *parport_pc_probe_port (unsigned long int base,
unsigned long int base_hi,
int irq, int dma,
......@@ -2114,39 +2117,30 @@ struct parport *parport_pc_probe_port (unsigned long int base,
{
struct parport_pc_private *priv;
struct parport_operations *ops;
struct parport tmp;
struct parport *p = &tmp;
struct parport *p;
int probedirq = PARPORT_IRQ_NONE;
struct resource *base_res;
struct resource *ECR_res = NULL;
struct resource *EPP_res = NULL;
char *fake_name = "parport probe";
/*
* Chicken and Egg problem. request_region() wants the name of
* the owner, but this instance will not know that name until
* after the parport_register_port() call. Give request_region()
* a fake name until after parport_register_port(), then use
* rename_region() to set correct name.
*/
base_res = request_region(base, 3, fake_name);
if (base_res == NULL)
return NULL;
ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL);
if (!ops)
goto out1;
priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
if (!priv) {
printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
release_region(base, 3);
return NULL;
}
ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
if (!ops) {
printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
base);
release_region(base, 3);
kfree (priv);
return NULL;
}
memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
if (!priv)
goto out2;
/* a misnomer, actually - it's allocate and reserve parport number */
p = parport_register_port(base, irq, dma, ops);
if (!p)
goto out3;
base_res = request_region(base, 3, p->name);
if (!base_res)
goto out4;
memcpy(ops, &parport_pc_ops, sizeof (struct parport_operations));
priv->ctr = 0xc;
priv->ctr_writable = ~0x10;
priv->ecr = 0;
......@@ -2154,59 +2148,37 @@ struct parport *parport_pc_probe_port (unsigned long int base,
priv->dma_buf = 0;
priv->dma_handle = 0;
priv->dev = dev;
p->base = base;
INIT_LIST_HEAD(&priv->list);
priv->port = p;
p->base_hi = base_hi;
p->irq = irq;
p->dma = dma;
p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
p->ops = ops;
p->private_data = priv;
p->physport = p;
if (base_hi) {
ECR_res = request_region(base_hi, 3, fake_name);
ECR_res = request_region(base_hi, 3, p->name);
if (ECR_res)
parport_ECR_present(p);
}
if (base != 0x3bc) {
EPP_res = request_region(base+0x3, 5, fake_name);
EPP_res = request_region(base+0x3, 5, p->name);
if (EPP_res)
if (!parport_EPP_supported(p))
parport_ECPEPP_supported(p);
}
if (!parport_SPP_supported (p))
/* No port. */
goto errout;
goto out5;
if (priv->ecr)
parport_ECPPS2_supported(p);
else
parport_PS2_supported (p);
parport_PS2_supported(p);
if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
PARPORT_DMA_NONE, ops)))
goto errout;
/*
* Now the real name is known... Replace the fake name
* in the resources with the correct one.
*/
rename_region(base_res, p->name);
if (ECR_res)
rename_region(ECR_res, p->name);
if (EPP_res)
rename_region(EPP_res, p->name);
p->base_hi = base_hi;
p->modes = tmp.modes;
p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
p->private_data = priv;
printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
if (p->base_hi && priv->ecr)
printk(" (0x%lx)", p->base_hi);
p->irq = irq;
p->dma = dma;
if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p);
......@@ -2269,7 +2241,6 @@ struct parport *parport_pc_probe_port (unsigned long int base,
printk("]\n");
if (probedirq != PARPORT_IRQ_NONE)
printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
parport_proc_register(p);
/* If No ECP release the ports grabbed above. */
if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) {
......@@ -2330,28 +2301,40 @@ struct parport *parport_pc_probe_port (unsigned long int base,
/* Now that we've told the sharing engine about the port, and
found out its characteristics, let the high-level drivers
know about it. */
spin_lock(&ports_lock);
list_add(&priv->list, &ports_list);
spin_unlock(&ports_lock);
parport_announce_port (p);
return p;
errout:
release_region(p->base, 3);
out5:
if (ECR_res)
release_region(base_hi, 3);
if (EPP_res)
release_region(base+0x3, 5);
release_region(base, 3);
out4:
parport_put_port(p);
out3:
kfree (priv);
out2:
kfree (ops);
out1:
return NULL;
}
EXPORT_SYMBOL (parport_pc_probe_port);
void parport_pc_unregister_port (struct parport *p)
{
#ifdef CONFIG_PARPORT_PC_FIFO
struct parport_pc_private *priv = p->private_data;
#endif /* CONFIG_PARPORT_PC_FIFO */
struct parport_operations *ops = p->ops;
parport_remove_port(p);
spin_lock(&ports_lock);
list_del_init(&priv->list);
spin_unlock(&ports_lock);
if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE)
......@@ -2361,7 +2344,6 @@ void parport_pc_unregister_port (struct parport *p)
release_region(p->base + 3, p->size - 3);
if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3);
parport_proc_unregister(p);
#ifdef CONFIG_PARPORT_PC_FIFO
if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE,
......@@ -2369,10 +2351,12 @@ void parport_pc_unregister_port (struct parport *p)
priv->dma_handle);
#endif /* CONFIG_PARPORT_PC_FIFO */
kfree (p->private_data);
parport_unregister_port(p);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
}
EXPORT_SYMBOL (parport_pc_unregister_port);
#ifdef CONFIG_PCI
/* ITE support maintained by Rich Liu <richliu@poorman.org> */
......@@ -2931,45 +2915,57 @@ static int __init parport_pc_find_ports (int autoirq, int autodma)
return count;
}
int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma)
{
int count = 0, i = 0;
/* try to activate any PnP parports first */
pnp_register_driver(&parport_pc_pnp_driver);
/*
* Piles of crap below pretend to be a parser for module and kernel
* parameters. Say "thank you" to whoever had come up with that
* syntax and keep in mind that code below is a cleaned up version.
*/
if (io && *io) {
/* Only probe the ports we were given. */
user_specified = 1;
do {
if ((*io_hi) == PARPORT_IOHI_AUTO)
*io_hi = 0x400 + *io;
if (parport_pc_probe_port(*(io++), *(io_hi++),
*(irq++), *(dma++), NULL))
count++;
} while (*io && (++i < PARPORT_PC_MAX_PORTS));
} else {
count += parport_pc_find_ports (irq[0], dma[0]);
static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] =
{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
static int __init parport_parse_param(const char *s, int *val,
int automatic, int none, int nofifo)
{
if (!s)
return 0;
if (!strncmp(s, "auto", 4))
*val = automatic;
else if (!strncmp(s, "none", 4))
*val = none;
else if (nofifo && !strncmp(s, "nofifo", 4))
*val = nofifo;
else {
char *ep;
unsigned long r = simple_strtoul(s, &ep, 0);
if (ep != s)
*val = r;
else {
printk(KERN_ERR "parport: bad specifier `%s'\n", s);
return -1;
}
}
return 0;
}
return count;
static int __init parport_parse_irq(const char *irqstr, int *val)
{
return parport_parse_param(irqstr, val, PARPORT_IRQ_AUTO,
PARPORT_IRQ_NONE, 0);
}
/* Exported symbols. */
EXPORT_SYMBOL (parport_pc_probe_port);
EXPORT_SYMBOL (parport_pc_unregister_port);
static int __init parport_parse_dma(const char *dmastr, int *val)
{
return parport_parse_param(dmastr, val, PARPORT_DMA_AUTO,
PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO);
}
#ifdef MODULE
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
static int io_hi[PARPORT_PC_MAX_PORTS+1] =
{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
MODULE_DESCRIPTION("PC-style parallel port driver");
MODULE_LICENSE("GPL");
static const char *irq[PARPORT_PC_MAX_PORTS];
static const char *dma[PARPORT_PC_MAX_PORTS];
MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
......@@ -2985,22 +2981,22 @@ MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
MODULE_PARM(verbose_probing, "i");
#endif
int init_module(void)
{
/* Work out how many ports we have, then get parport_share to parse
the irq values. */
static int __init parse_parport_params(void)
{
unsigned int i;
int ret;
for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
if (i) {
if (parport_parse_irqs(i, irq, irqval)) return 1;
if (parport_parse_dmas(i, dma, dmaval)) return 1;
int val;
for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) {
if (parport_parse_irq(irq[i], &val))
return 1;
irqval[i] = val;
if (parport_parse_dma(dma[i], &val))
return 1;
dmaval[i] = val;
}
else {
if (!io[0]) {
/* The user can make us use any IRQs or DMAs we find. */
int val;
if (irq[0] && !parport_parse_irqs (1, irq, &val))
if (irq[0] && !parport_parse_irq(irq[0], &val))
switch (val) {
case PARPORT_IRQ_NONE:
case PARPORT_IRQ_AUTO:
......@@ -3013,7 +3009,7 @@ int init_module(void)
"to specify one\n");
}
if (dma[0] && !parport_parse_dmas (1, dma, &val))
if (dma[0] && !parport_parse_dma(dma[0], &val))
switch (val) {
case PARPORT_DMA_NONE:
case PARPORT_DMA_AUTO:
......@@ -3026,29 +3022,144 @@ int init_module(void)
"to specify one\n");
}
}
return 0;
}
ret = !parport_pc_init (io, io_hi, irqval, dmaval);
if (ret && registered_parport)
pci_unregister_driver (&parport_pc_pci_driver);
#else
static int parport_setup_ptr __initdata = 0;
/*
* Acceptable parameters:
*
* parport=0
* parport=auto
* parport=0xBASE[,IRQ[,DMA]]
*
* IRQ/DMA may be numeric or 'auto' or 'none'
*/
static int __init parport_setup (char *str)
{
char *endptr;
char *sep;
int val;
if (!str || !*str || (*str == '0' && !*(str+1))) {
/* Disable parport if "parport=0" in cmdline */
io[0] = PARPORT_DISABLE;
return 1;
}
if (!strncmp (str, "auto", 4)) {
irqval[0] = PARPORT_IRQ_AUTO;
dmaval[0] = PARPORT_DMA_AUTO;
return 1;
}
return ret;
val = simple_strtoul (str, &endptr, 0);
if (endptr == str) {
printk (KERN_WARNING "parport=%s not understood\n", str);
return 1;
}
if (parport_setup_ptr == PARPORT_PC_MAX_PORTS) {
printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
return 1;
}
io[parport_setup_ptr] = val;
irqval[parport_setup_ptr] = PARPORT_IRQ_NONE;
dmaval[parport_setup_ptr] = PARPORT_DMA_NONE;
sep = strchr(str, ',');
if (sep++) {
if (parport_parse_irq(sep, &val))
return 1;
irqval[parport_setup_ptr] = val;
sep = strchr(sep, ',');
if (sep++) {
if (parport_parse_dma(sep, &val))
return 1;
dmaval[parport_setup_ptr] = val;
}
}
parport_setup_ptr++;
return 1;
}
void cleanup_module(void)
static int __init parse_parport_params(void)
{
/* We ought to keep track of which ports are actually ours. */
struct parport *p = parport_enumerate(), *tmp;
return io[0] == PARPORT_DISABLE;
}
if (!user_specified)
pci_unregister_driver (&parport_pc_pci_driver);
__setup ("parport=", parport_setup);
#endif
while (p) {
tmp = p->next;
if (p->modes & PARPORT_MODE_PCSPP)
parport_pc_unregister_port (p);
/* "Parser" ends here */
static int __init parport_pc_init(void)
{
int count = 0;
p = tmp;
if (parse_parport_params())
return -EINVAL;
/* try to activate any PnP parports first */
pnp_register_driver(&parport_pc_pnp_driver);
if (io[0]) {
int i;
/* Only probe the ports we were given. */
user_specified = 1;
for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) {
if (!io[i])
break;
if ((io_hi[i]) == PARPORT_IOHI_AUTO)
io_hi[i] = 0x400 + io[i];
if (parport_pc_probe_port(io[i], io_hi[i],
irqval[i], dmaval[i], NULL))
count++;
}
} else {
count += parport_pc_find_ports (irqval[0], dmaval[0]);
if (!count && registered_parport)
pci_unregister_driver (&parport_pc_pci_driver);
}
if (!count) {
pnp_unregister_driver (&parport_pc_pnp_driver);
return -ENODEV;
}
return 0;
}
static void __exit parport_pc_exit(void)
{
if (registered_parport)
pci_unregister_driver (&parport_pc_pci_driver);
spin_lock(&ports_lock);
while (!list_empty(&ports_list)) {
struct parport_pc_private *priv;
struct parport *port;
priv = list_entry(ports_list.next,
struct parport_pc_private, list);
port = priv->port;
spin_unlock(&ports_lock);
parport_pc_unregister_port(port);
spin_lock(&ports_lock);
}
spin_unlock(&ports_lock);
pnp_unregister_driver (&parport_pc_pnp_driver);
}
#endif
MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
MODULE_DESCRIPTION("PC-style parallel port driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
MODULE_DESCRIPTION("PC-style parallel port driver");
MODULE_LICENSE("GPL");
module_init(parport_pc_init)
module_exit(parport_pc_exit)
......@@ -286,39 +286,49 @@ static struct parport_operations parport_sunbpp_ops =
.owner = THIS_MODULE,
};
typedef struct {
struct list_head list;
struct parport *port;
} Node;
/* no locks, everything's serialized */
static LIST_HEAD(port_list);
static int __init init_one_port(struct sbus_dev *sdev)
{
struct parport *p;
/* at least in theory there may be a "we don't dma" case */
struct parport_operations *ops;
unsigned long base;
int irq, dma, err, size;
int irq, dma, err = 0, size;
struct bpp_regs *regs;
unsigned char value_tcr;
Node *node;
dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
node = kmalloc(sizeof(Node), GFP_KERNEL);
if (!node)
goto out0;
irq = sdev->irqs[0];
base = sbus_ioremap(&sdev->resource[0], 0,
sdev->reg_addrs[0].reg_size,
"sunbpp");
if (!base)
goto out1;
size = sdev->reg_addrs[0].reg_size;
dma = PARPORT_DMA_NONE;
dprintk(("alloc(ppops), "));
ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
if (!ops) {
sbus_iounmap(base, size);
return 0;
}
if (!ops)
goto out2;
memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
dprintk(("register_port\n"));
if (!(p = parport_register_port(base, irq, dma, ops))) {
kfree(ops);
sbus_iounmap(base, size);
return 0;
}
if (!(p = parport_register_port(base, irq, dma, ops)))
goto out3;
p->size = size;
......@@ -327,14 +337,10 @@ static int __init init_one_port(struct sbus_dev *sdev)
if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
SA_SHIRQ, p->name, p)) != 0) {
dprintk(("ERROR %d\n", err));
parport_unregister_port(p);
kfree(ops);
sbus_iounmap(base, size);
return err;
} else {
dprintk(("OK\n"));
parport_sunbpp_enable_irq(p);
goto out4;
}
dprintk(("OK\n"));
parport_sunbpp_enable_irq(p);
regs = (struct bpp_regs *)p->base;
dprintk((KERN_DEBUG "forward\n"));
......@@ -343,17 +349,25 @@ static int __init init_one_port(struct sbus_dev *sdev)
sbus_writeb(value_tcr, &regs->p_tcr);
printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
parport_proc_register(p);
node->port = p;
list_add(&node->list, &port_list);
parport_announce_port (p);
return 1;
out4:
parport_put_port(p);
out3:
kfree(ops);
out2:
sbus_iounmap(base, size);
out1:
kfree(node);
out0:
return err;
}
#ifdef MODULE
int init_module(void)
#else
int __init parport_sunbpp_init(void)
#endif
static int __init parport_sunbpp_init(void)
{
struct sbus_bus *sbus;
struct sbus_dev *sdev;
......@@ -368,34 +382,30 @@ int __init parport_sunbpp_init(void)
return count ? 0 : -ENODEV;
}
#ifdef MODULE
MODULE_AUTHOR("Derrick J Brashear");
MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
void
cleanup_module(void)
static void __exit parport_sunbpp_exit(void)
{
struct parport *p = parport_enumerate();
while (p) {
struct parport *next = p->next;
if (1/*p->modes & PARPORT_MODE_PCSPP*/) {
struct parport_operations *ops = p->ops;
if (p->irq != PARPORT_IRQ_NONE) {
parport_sunbpp_disable_irq(p);
free_irq(p->irq, p);
}
sbus_iounmap(p->base, p->size);
parport_proc_unregister(p);
parport_unregister_port(p);
kfree (ops);
while (!list_empty(port_list)) {
Node *node = list_entry(port_list.next, Node, list);
struct parport *p = node->port;
struct parport_operations *ops = p->ops;
parport_remove_port(p);
if (p->irq != PARPORT_IRQ_NONE) {
parport_sunbpp_disable_irq(p);
free_irq(p->irq, p);
}
p = next;
sbus_iounmap(p->base, p->size);
parport_put_port(p);
kfree (ops);
list_del(&node->list);
kfree (node);
}
}
#endif
MODULE_AUTHOR("Derrick J Brashear");
MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
MODULE_LICENSE("GPL");
module_init(parport_sunbpp_init)
module_exit(parport_sunbpp_exit)
......@@ -5,6 +5,7 @@
* Philip Blundell <Philip.Blundell@pobox.com>
*/
#include <linux/module.h>
#include <linux/parport.h>
#include <linux/ctype.h>
#include <linux/string.h>
......@@ -212,3 +213,4 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
parport_close (dev);
return retval;
}
EXPORT_SYMBOL(parport_device_id);
......@@ -14,6 +14,8 @@
#include <linux/string.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
......@@ -479,21 +481,20 @@ int parport_device_proc_unregister(struct pardevice *device)
return 0;
}
int parport_default_proc_register(void)
static int __init parport_default_proc_register(void)
{
parport_default_sysctl_table.sysctl_header =
register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
return 0;
}
int parport_default_proc_unregister(void)
static void __exit parport_default_proc_unregister(void)
{
if (parport_default_sysctl_table.sysctl_header) {
unregister_sysctl_table(parport_default_sysctl_table.
sysctl_header);
parport_default_sysctl_table.sysctl_header = NULL;
}
return 0;
}
#else /* no sysctl or no procfs*/
......@@ -518,13 +519,19 @@ int parport_device_proc_unregister(struct pardevice *device)
return 0;
}
int parport_default_proc_register (void)
static int __init parport_default_proc_register (void)
{
return 0;
}
int parport_default_proc_unregister (void)
static void __exit parport_default_proc_unregister (void)
{
return 0;
}
#endif
EXPORT_SYMBOL(parport_device_proc_register);
EXPORT_SYMBOL(parport_device_proc_unregister);
module_init(parport_default_proc_register)
module_exit(parport_default_proc_unregister)
......@@ -41,14 +41,14 @@
unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
int parport_default_spintime = DEFAULT_SPIN_TIME;
static struct parport *portlist = NULL, *portlist_tail = NULL;
static LIST_HEAD(portlist);
static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
/* list of all allocated ports, sorted by ->number */
static LIST_HEAD(all_ports);
static spinlock_t full_list_lock = SPIN_LOCK_UNLOCKED;
static struct parport_driver *driver_chain = NULL;
static LIST_HEAD(drivers);
static DECLARE_MUTEX(registration_lock);
......@@ -105,16 +105,16 @@ static void attach_driver_chain(struct parport *port)
{
/* caller has exclusive registration_lock */
struct parport_driver *drv;
for (drv = driver_chain; drv; drv = drv->next)
list_for_each_entry(drv, &drivers, list)
drv->attach(port);
}
/* Call detach(port) for each registered driver. */
static void detach_driver_chain(struct parport *port)
{
/* caller has exclusive registration_lock */
struct parport_driver *drv;
for (drv = driver_chain; drv; drv = drv->next)
/* caller has exclusive registration_lock */
list_for_each_entry(drv, &drivers, list)
drv->detach (port);
}
......@@ -155,22 +155,13 @@ int parport_register_driver (struct parport_driver *drv)
{
struct parport *port;
if (!portlist)
if (list_empty(&portlist))
get_lowlevel_driver ();
/* We have to take the portlist lock for this to be sure
* that port is valid for the duration of the callback. */
/* This is complicated by the fact that attach must be allowed
* to block, so we can't be holding any spinlocks when we call
* it. But we need to hold a spinlock to iterate over the
* list of ports.. */
down(&registration_lock);
for (port = portlist; port; port = port->next)
list_for_each_entry(port, &portlist, list)
drv->attach(port);
drv->next = driver_chain;
driver_chain = drv;
list_add(&drv->list, &drivers);
up(&registration_lock);
return 0;
......@@ -193,33 +184,14 @@ int parport_register_driver (struct parport_driver *drv)
* finished by the time this function returns.
**/
void parport_unregister_driver (struct parport_driver *arg)
void parport_unregister_driver (struct parport_driver *drv)
{
struct parport_driver *drv, *olddrv = NULL;
struct parport *port;
down(&registration_lock);
drv = driver_chain;
while (drv) {
if (drv == arg) {
struct parport *port;
if (olddrv)
olddrv->next = drv->next;
else
driver_chain = drv->next;
/* Call the driver's detach routine for each
* port to clean up any resources that the
* attach routine acquired. */
for (port = portlist; port; port = port->next)
drv->detach (port);
up(&registration_lock);
return;
}
olddrv = drv;
drv = drv->next;
}
list_del_init(&drv->list);
list_for_each_entry(port, &portlist, list)
drv->detach(port);
up(&registration_lock);
}
......@@ -277,28 +249,6 @@ void parport_put_port (struct parport *port)
return;
}
/**
* parport_enumerate - return a list of the system's parallel ports
*
* This returns the head of the list of parallel ports in the
* system, as a &struct parport. The structure that is returned
* describes the first port in the list, and its 'next' member
* points to the next port, or %NULL if it's the last port.
*
* If there are no parallel ports in the system,
* parport_enumerate() will return %NULL.
**/
struct parport *parport_enumerate(void)
{
/* Don't use this: use parport_register_driver instead. */
if (!portlist)
get_lowlevel_driver ();
return portlist;
}
/**
* parport_register_port - register a parallel port
* @base: base I/O address
......@@ -322,7 +272,7 @@ struct parport *parport_enumerate(void)
* parport_announce_port().
*
* The @ops structure is allocated by the caller, and must not be
* deallocated before calling parport_unregister_port().
* deallocated before calling parport_remove_port().
*
* If there is no memory to allocate a new parport structure,
* this function will return %NULL.
......@@ -350,7 +300,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
tmp->dma = dma;
tmp->muxport = tmp->daisy = tmp->muxsel = -1;
tmp->modes = 0;
tmp->next = NULL;
INIT_LIST_HEAD(&tmp->list);
tmp->devices = tmp->cad = NULL;
tmp->flags = 0;
tmp->ops = ops;
......@@ -413,49 +363,36 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
void parport_announce_port (struct parport *port)
{
int i;
#ifdef CONFIG_PARPORT_1284
/* Analyse the IEEE1284.3 topology of the port. */
if (parport_daisy_init (port) == 0) {
/* No devices were detected. Perhaps they are in some
funny state; let's try to reset them and see if
they wake up. */
parport_daisy_fini (port);
parport_write_control (port, PARPORT_CONTROL_SELECT);
udelay (50);
parport_write_control (port,
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT);
udelay (50);
parport_daisy_init (port);
}
parport_daisy_init(port);
#endif
parport_proc_register(port);
down(&registration_lock);
/* We are locked against anyone else performing alterations, but
* because of parport_enumerate people can still _read_ the list
* while we are changing it; so be careful..
*
* It's okay to have portlist_tail a little bit out of sync
* since it's only used for changing the list, not for reading
* from it.
*/
spin_lock_irq(&parportlist_lock);
if (portlist_tail)
portlist_tail->next = port;
portlist_tail = port;
if (!portlist)
portlist = port;
list_add_tail(&port->list, &portlist);
for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1];
if (slave)
list_add_tail(&slave->list, &portlist);
}
spin_unlock_irq(&parportlist_lock);
/* Let drivers know that a new port has arrived. */
/* Let drivers know that new port(s) has arrived. */
attach_driver_chain (port);
for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1];
if (slave)
attach_driver_chain(slave);
}
up(&registration_lock);
}
/**
* parport_unregister_port - deregister a parallel port
* parport_remove_port - deregister a parallel port
* @port: parallel port to deregister
*
* When a parallel port driver is forcibly unloaded, or a
......@@ -473,44 +410,46 @@ void parport_announce_port (struct parport *port)
* with @port as the parameter.
**/
void parport_unregister_port(struct parport *port)
void parport_remove_port(struct parport *port)
{
struct parport *p;
int i;
down(&registration_lock);
port->ops = &dead_ops;
/* Spread the word. */
detach_driver_chain (port);
#ifdef CONFIG_PARPORT_1284
/* Forget the IEEE1284.3 topology of the port. */
parport_daisy_fini (port);
parport_daisy_fini(port);
for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1];
if (!slave)
continue;
detach_driver_chain(slave);
parport_daisy_fini(slave);
}
#endif
port->ops = &dead_ops;
spin_lock(&parportlist_lock);
/* We are protected from other people changing the list, but
* they can still see it (using parport_enumerate). So be
* careful about the order of writes.. */
if (portlist == port) {
if ((portlist = port->next) == NULL)
portlist_tail = NULL;
} else {
for (p = portlist; (p != NULL) && (p->next != port);
p=p->next);
if (p) {
if ((p->next = port->next) == NULL)
portlist_tail = p;
}
else printk (KERN_WARNING
"%s not found in port list!\n", port->name);
list_del_init(&port->list);
for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1];
if (slave)
list_del_init(&slave->list);
}
spin_unlock(&parportlist_lock);
up(&registration_lock);
/* Yes, parport_enumerate _is_ unsafe. Don't use it. */
parport_put_port (port);
parport_proc_unregister(port);
for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1];
if (slave)
parport_put_port(slave);
}
}
/**
......@@ -607,9 +546,8 @@ parport_register_device(struct parport *port, const char *name,
/* We up our own module reference count, and that of the port
on which a device is to be registered, to ensure that
neither of us gets unloaded while we sleep in (e.g.)
kmalloc. To be absolutely safe, we have to require that
our caller doesn't sleep in between parport_enumerate and
parport_register_device.. */
kmalloc.
*/
if (!try_module_get(port->ops->owner)) {
return NULL;
}
......@@ -751,11 +689,6 @@ void parport_unregister_device(struct pardevice *dev)
module_put(port->ops->owner);
parport_put_port (port);
/* Yes, that's right, someone _could_ still have a pointer to
* port, if they used parport_enumerate. That's why they
* shouldn't use it (and use parport_register_driver instead)..
*/
}
/**
......@@ -774,15 +707,16 @@ struct parport *parport_find_number (int number)
{
struct parport *port, *result = NULL;
if (!portlist)
if (list_empty(&portlist))
get_lowlevel_driver ();
spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next)
list_for_each_entry(port, &portlist, list) {
if (port->number == number) {
result = parport_get_port (port);
break;
}
}
spin_unlock (&parportlist_lock);
return result;
}
......@@ -803,15 +737,16 @@ struct parport *parport_find_base (unsigned long base)
{
struct parport *port, *result = NULL;
if (!portlist)
if (list_empty(&portlist))
get_lowlevel_driver ();
spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next)
list_for_each_entry(port, &portlist, list) {
if (port->base == base) {
result = parport_get_port (port);
break;
}
}
spin_unlock (&parportlist_lock);
return result;
}
......@@ -1060,41 +995,21 @@ void parport_release(struct pardevice *dev)
}
}
static int parport_parse_params (int nports, const char *str[], int val[],
int automatic, int none, int nofifo)
{
unsigned int i;
for (i = 0; i < nports && str[i]; i++) {
if (!strncmp(str[i], "auto", 4))
val[i] = automatic;
else if (!strncmp(str[i], "none", 4))
val[i] = none;
else if (nofifo && !strncmp(str[i], "nofifo", 4))
val[i] = nofifo;
else {
char *ep;
unsigned long r = simple_strtoul(str[i], &ep, 0);
if (ep != str[i])
val[i] = r;
else {
printk(KERN_ERR "parport: bad specifier `%s'\n", str[i]);
return -1;
}
}
}
return 0;
}
int parport_parse_irqs(int nports, const char *irqstr[], int irqval[])
{
return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO,
PARPORT_IRQ_NONE, 0);
}
/* Exported symbols for modules. */
EXPORT_SYMBOL(parport_claim);
EXPORT_SYMBOL(parport_claim_or_block);
EXPORT_SYMBOL(parport_release);
EXPORT_SYMBOL(parport_register_port);
EXPORT_SYMBOL(parport_announce_port);
EXPORT_SYMBOL(parport_remove_port);
EXPORT_SYMBOL(parport_register_driver);
EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number);
EXPORT_SYMBOL(parport_find_base);
int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[])
{
return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO,
PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO);
}
MODULE_LICENSE("GPL");
......@@ -592,7 +592,6 @@ static int uss720_probe(struct usb_interface *intf,
goto probe_abort_port;
}
#endif
parport_proc_register(pp);
parport_announce_port(pp);
usb_set_intfdata (intf, pp);
......@@ -600,7 +599,7 @@ static int uss720_probe(struct usb_interface *intf,
#if 0
probe_abort_port:
parport_unregister_port(pp);
parport_put_port(pp);
#endif
probe_abort:
kfree(priv);
......@@ -615,12 +614,12 @@ static void uss720_disconnect(struct usb_interface *intf)
usb_set_intfdata (intf, NULL);
if (pp) {
priv = pp->private_data;
parport_remove_port(pp);
#if 0
usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
#endif
priv->usbdev = NULL;
parport_proc_unregister(pp);
parport_unregister_port(pp);
parport_put_port(pp);
kfree(priv);
}
}
......
......@@ -294,7 +294,7 @@ struct parport {
struct pardevice *waithead;
struct pardevice *waittail;
struct parport *next;
struct list_head list;
unsigned int flags;
void *sysctl_table;
......@@ -313,6 +313,7 @@ struct parport {
atomic_t ref_count;
struct list_head full_list;
struct parport *slaves[3];
};
#define DEFAULT_SPIN_TIME 500 /* us */
......@@ -321,7 +322,7 @@ struct parport_driver {
const char *name;
void (*attach) (struct parport *);
void (*detach) (struct parport *);
struct parport_driver *next;
struct list_head list;
};
/* parport_register_port registers a new parallel port at the given
......@@ -339,12 +340,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
void parport_announce_port (struct parport *port);
/* Unregister a port. */
extern void parport_unregister_port(struct parport *port);
/* parport_enumerate returns a pointer to the linked list of all the
ports in this machine. DON'T USE THIS. Use
parport_register_driver instead. */
struct parport *parport_enumerate(void);
extern void parport_remove_port(struct parport *port);
/* Register a new high-level driver. */
extern int parport_register_driver (struct parport_driver *);
......@@ -451,9 +447,6 @@ static __inline__ int parport_yield_blocking(struct pardevice *dev)
#define PARPORT_FLAG_EXCL (1<<1) /* EXCL driver registered. */
extern int parport_parse_irqs(int, const char *[], int irqval[]);
extern int parport_parse_dmas(int, const char *[], int dmaval[]);
/* IEEE1284 functions */
extern void parport_ieee1284_interrupt (int, void *, struct pt_regs *);
extern int parport_negotiate (struct parport *, int mode);
......@@ -538,8 +531,6 @@ extern int parport_proc_register(struct parport *pp);
extern int parport_proc_unregister(struct parport *pp);
extern int parport_device_proc_register(struct pardevice *device);
extern int parport_device_proc_unregister(struct pardevice *device);
extern int parport_default_proc_register(void);
extern int parport_default_proc_unregister(void);
/* If PC hardware is the only type supported, we can optimise a bit. */
#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE)) && !(defined(CONFIG_PARPORT_SUNBPP) || defined(CONFIG_PARPORT_SUNBPP_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
......
......@@ -39,6 +39,8 @@ struct parport_pc_private {
char *dma_buf;
dma_addr_t dma_handle;
struct pci_dev *dev;
struct list_head list;
struct parport *port;
};
static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment