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) ...@@ -862,10 +862,9 @@ static void lp_detach (struct parport *port)
} }
static struct parport_driver lp_driver = { static struct parport_driver lp_driver = {
"lp", .name = "lp",
lp_attach, .attach = lp_attach,
lp_detach, .detach = lp_detach,
NULL
}; };
int __init lp_init (void) int __init lp_init (void)
......
...@@ -463,10 +463,9 @@ tipar_detach(struct parport *port) ...@@ -463,10 +463,9 @@ tipar_detach(struct parport *port)
} }
static struct parport_driver tipar_driver = { static struct parport_driver tipar_driver = {
"tipar", .name = "tipar",
tipar_attach, .attach = tipar_attach,
tipar_detach, .detach = tipar_detach,
NULL
}; };
int __init int __init
......
...@@ -818,10 +818,9 @@ static void cq_detach(struct parport *port) ...@@ -818,10 +818,9 @@ static void cq_detach(struct parport *port)
} }
static struct parport_driver cqcam_driver = { static struct parport_driver cqcam_driver = {
"cqcam", .name = "cqcam",
cq_attach, .attach = cq_attach,
cq_detach, .detach = cq_detach,
NULL
}; };
static int __init cqcam_init (void) static int __init cqcam_init (void)
......
...@@ -803,10 +803,9 @@ static void cpia_pp_attach (struct parport *port) ...@@ -803,10 +803,9 @@ static void cpia_pp_attach (struct parport *port)
} }
static struct parport_driver cpia_pp_driver = { static struct parport_driver cpia_pp_driver = {
"cpia_pp", .name = "cpia_pp",
cpia_pp_attach, .attach = cpia_pp_attach,
cpia_pp_detach, .detach = cpia_pp_detach,
NULL
}; };
int cpia_pp_init(void) int cpia_pp_init(void)
...@@ -853,11 +852,6 @@ int init_module(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(); return cpia_pp_init();
} }
......
...@@ -959,10 +959,9 @@ static void w9966_detach(struct parport *port) ...@@ -959,10 +959,9 @@ static void w9966_detach(struct parport *port)
static struct parport_driver w9966_ppd = { static struct parport_driver w9966_ppd = {
W9966_DRIVERNAME, .name = W9966_DRIVERNAME,
w9966_attach, .attach = w9966_attach,
w9966_detach, .detach = w9966_detach,
NULL
}; };
// Module entry point // Module entry point
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the kernel Parallel port device drivers. # 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) ifeq ($(CONFIG_PARPORT_1284),y)
parport-objs += daisy.o probe.o parport-objs += daisy.o probe.o
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/module.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -79,6 +80,7 @@ static struct parport *clone_parport (struct parport *real, int muxport) ...@@ -79,6 +80,7 @@ static struct parport *clone_parport (struct parport *real, int muxport)
extra->portnum = real->portnum; extra->portnum = real->portnum;
extra->physport = real; extra->physport = real;
extra->muxport = muxport; extra->muxport = muxport;
real->slaves[muxport-1] = extra;
} }
return extra; return extra;
...@@ -93,7 +95,9 @@ int parport_daisy_init (struct parport *port) ...@@ -93,7 +95,9 @@ int parport_daisy_init (struct parport *port)
static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" }; static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
int num_ports; int num_ports;
int i; int i;
int last_try = 0;
again:
/* Because this is called before any other devices exist, /* Because this is called before any other devices exist,
* we don't have to claim exclusive access. */ * we don't have to claim exclusive access. */
...@@ -126,7 +130,7 @@ int parport_daisy_init (struct parport *port) ...@@ -126,7 +130,7 @@ int parport_daisy_init (struct parport *port)
/* Analyse that port too. We won't recurse /* Analyse that port too. We won't recurse
forever because of the 'port->muxport < 0' forever because of the 'port->muxport < 0'
test above. */ test above. */
parport_announce_port (extra); parport_daisy_init(extra);
} }
} }
...@@ -148,6 +152,21 @@ int parport_daisy_init (struct parport *port) ...@@ -148,6 +152,21 @@ int parport_daisy_init (struct parport *port)
kfree (deviceid); 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; return detected;
} }
...@@ -634,3 +653,13 @@ int parport_find_class (parport_device_class cls, int from) ...@@ -634,3 +653,13 @@ int parport_find_class (parport_device_class cls, int from)
spin_unlock(&topology_lock); spin_unlock(&topology_lock);
return res; 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 @@ ...@@ -17,6 +17,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -806,3 +807,15 @@ long parport_set_timeout (struct pardevice *dev, long inactivity) ...@@ -806,3 +807,15 @@ long parport_set_timeout (struct pardevice *dev, long inactivity)
return old; 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 @@ ...@@ -15,6 +15,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -908,4 +909,13 @@ size_t parport_ieee1284_epp_read_addr (struct parport *port, ...@@ -908,4 +909,13 @@ size_t parport_ieee1284_epp_read_addr (struct parport *port,
return ret; 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 = { ...@@ -234,7 +234,7 @@ static struct parport_operations pp_amiga_ops = {
/* ----------- Initialisation code --------------------------------- */ /* ----------- Initialisation code --------------------------------- */
int __init parport_amiga_init(void) static int __init parport_amiga_init(void)
{ {
struct parport *p; struct parport *p;
int err; int err;
...@@ -262,26 +262,24 @@ int __init parport_amiga_init(void) ...@@ -262,26 +262,24 @@ int __init parport_amiga_init(void)
this_port = p; this_port = p;
printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
/* XXX: set operating mode */ /* XXX: set operating mode */
parport_proc_register(p);
parport_announce_port(p); parport_announce_port(p);
return 0; return 0;
out_irq: out_irq:
parport_unregister_port(p); parport_put_port(p);
out_port: out_port:
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
out_mem: out_mem:
return err; 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) if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_AMIGA_CIAA_FLG, this_port); free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
parport_proc_unregister(this_port); parport_put_port(this_port);
parport_unregister_port(this_port);
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
} }
......
...@@ -104,7 +104,7 @@ static struct parport_operations parport_arc_ops = ...@@ -104,7 +104,7 @@ static struct parport_operations parport_arc_ops =
/* --- Initialisation code -------------------------------- */ /* --- Initialisation code -------------------------------- */
int parport_arc_init(void) static int parport_arc_init(void)
{ {
/* Archimedes hardware provides only one port, at a fixed address */ /* Archimedes hardware provides only one port, at a fixed address */
struct parport *p; struct parport *p;
...@@ -129,10 +129,11 @@ int parport_arc_init(void) ...@@ -129,10 +129,11 @@ int parport_arc_init(void)
printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n", printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
p->irq); p->irq);
parport_proc_register(p);
/* Tell the high-level drivers about the port. */ /* Tell the high-level drivers about the port. */
parport_announce_port (p); parport_announce_port (p);
return 1; return 1;
} }
module_init(parport_arc_init)
...@@ -185,8 +185,7 @@ static struct parport_operations parport_atari_ops = { ...@@ -185,8 +185,7 @@ static struct parport_operations parport_atari_ops = {
}; };
int __init static int __init parport_atari_init(void)
parport_atari_init(void)
{ {
struct parport *p; struct parport *p;
unsigned long flags; unsigned long flags;
...@@ -208,43 +207,34 @@ parport_atari_init(void) ...@@ -208,43 +207,34 @@ parport_atari_init(void)
IRQ_MFP_BUSY, PARPORT_DMA_NONE, IRQ_MFP_BUSY, PARPORT_DMA_NONE,
&parport_atari_ops); &parport_atari_ops);
if (!p) if (!p)
return 0; return -ENODEV;
if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt, if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
IRQ_TYPE_SLOW, p->name, p)) { IRQ_TYPE_SLOW, p->name, p)) {
parport_unregister_port (p); parport_put_port (p);
return 0; return -ENODEV;
} }
this_port = p; this_port = p;
printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name); printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
parport_proc_register(p);
parport_announce_port (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_AUTHOR("Andreas Schwab");
MODULE_DESCRIPTION("Parport Driver for Atari builtin Port"); MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port"); MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
int module_init(parport_atari_init)
init_module(void) module_exit(parport_atari_exit)
{
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
...@@ -412,7 +412,6 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base, ...@@ -412,7 +412,6 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
} }
#undef printmode #undef printmode
printk("]\n"); printk("]\n");
parport_proc_register(p);
if (p->irq != PARPORT_IRQ_NONE) { if (p->irq != PARPORT_IRQ_NONE) {
if (request_irq (p->irq, parport_gsc_interrupt, if (request_irq (p->irq, parport_gsc_interrupt,
...@@ -483,17 +482,17 @@ static void __devexit parport_remove_chip(struct parisc_device *dev) ...@@ -483,17 +482,17 @@ static void __devexit parport_remove_chip(struct parisc_device *dev)
if (p) { if (p) {
struct parport_gsc_private *priv = p->private_data; struct parport_gsc_private *priv = p->private_data;
struct parport_operations *ops = p->ops; struct parport_operations *ops = p->ops;
parport_remove_port(p);
if (p->dma != PARPORT_DMA_NONE) if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma); free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE) if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p); free_irq(p->irq, p);
parport_proc_unregister(p);
if (priv->dma_buf) if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE, pci_free_consistent(priv->dev, PAGE_SIZE,
priv->dma_buf, priv->dma_buf,
priv->dma_handle); priv->dma_handle);
kfree (p->private_data); kfree (p->private_data);
parport_unregister_port(p); parport_put_port(p);
kfree (ops); /* hope no-one cached it */ kfree (ops); /* hope no-one cached it */
} }
} }
......
...@@ -320,7 +320,7 @@ static struct parport_operations pp_mfc3_ops = { ...@@ -320,7 +320,7 @@ static struct parport_operations pp_mfc3_ops = {
/* ----------- Initialisation code --------------------------------- */ /* ----------- Initialisation code --------------------------------- */
int __init parport_mfc3_init(void) static int __init parport_mfc3_init(void)
{ {
struct parport *p; struct parport *p;
int pias = 0; int pias = 0;
...@@ -360,7 +360,6 @@ int __init parport_mfc3_init(void) ...@@ -360,7 +360,6 @@ int __init parport_mfc3_init(void)
this_port[pias++] = p; this_port[pias++] = p;
printk(KERN_INFO "%s: Multiface III port using irq\n", p->name); printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
/* XXX: set operating mode */ /* XXX: set operating mode */
parport_proc_register(p);
p->private_data = (void *)piabase; p->private_data = (void *)piabase;
parport_announce_port (p); parport_announce_port (p);
...@@ -370,7 +369,7 @@ int __init parport_mfc3_init(void) ...@@ -370,7 +369,7 @@ int __init parport_mfc3_init(void)
continue; continue;
out_irq: out_irq:
parport_unregister_port(p); parport_put_port(p);
out_port: out_port:
release_mem_region(piabase, sizeof(struct pia)); release_mem_region(piabase, sizeof(struct pia));
} }
...@@ -378,20 +377,20 @@ int __init parport_mfc3_init(void) ...@@ -378,20 +377,20 @@ int __init parport_mfc3_init(void)
return pias ? 0 : -ENODEV; return pias ? 0 : -ENODEV;
} }
void __exit parport_mfc3_exit(void) static void __exit parport_mfc3_exit(void)
{ {
int i; int i;
for (i = 0; i < MAX_MFC; i++) { for (i = 0; i < MAX_MFC; i++) {
if (!this_port[i]) if (!this_port[i])
continue; continue;
parport_remove_port(this_port[i]);
if (!this_port[i]->irq != PARPORT_IRQ_NONE) { if (!this_port[i]->irq != PARPORT_IRQ_NONE) {
if (--use_cnt == 0) if (--use_cnt == 0)
free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); 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)); 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"); ...@@ -403,4 +402,3 @@ MODULE_LICENSE("GPL");
module_init(parport_mfc3_init) module_init(parport_mfc3_init)
module_exit(parport_mfc3_exit) module_exit(parport_mfc3_exit)
...@@ -2107,6 +2107,9 @@ static int __devinit parport_dma_probe (struct parport *p) ...@@ -2107,6 +2107,9 @@ static int __devinit parport_dma_probe (struct parport *p)
/* --- Initialisation code -------------------------------- */ /* --- 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, struct parport *parport_pc_probe_port (unsigned long int base,
unsigned long int base_hi, unsigned long int base_hi,
int irq, int dma, int irq, int dma,
...@@ -2114,39 +2117,30 @@ struct parport *parport_pc_probe_port (unsigned long int base, ...@@ -2114,39 +2117,30 @@ struct parport *parport_pc_probe_port (unsigned long int base,
{ {
struct parport_pc_private *priv; struct parport_pc_private *priv;
struct parport_operations *ops; struct parport_operations *ops;
struct parport tmp; struct parport *p;
struct parport *p = &tmp;
int probedirq = PARPORT_IRQ_NONE; int probedirq = PARPORT_IRQ_NONE;
struct resource *base_res; struct resource *base_res;
struct resource *ECR_res = NULL; struct resource *ECR_res = NULL;
struct resource *EPP_res = NULL; struct resource *EPP_res = NULL;
char *fake_name = "parport probe";
/* ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL);
* Chicken and Egg problem. request_region() wants the name of if (!ops)
* the owner, but this instance will not know that name until goto out1;
* 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;
priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
if (!priv) { if (!priv)
printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); goto out2;
release_region(base, 3);
return NULL; /* a misnomer, actually - it's allocate and reserve parport number */
} p = parport_register_port(base, irq, dma, ops);
ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); if (!p)
if (!ops) { goto out3;
printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
base); base_res = request_region(base, 3, p->name);
release_region(base, 3); if (!base_res)
kfree (priv); goto out4;
return NULL;
} memcpy(ops, &parport_pc_ops, sizeof (struct parport_operations));
memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
priv->ctr = 0xc; priv->ctr = 0xc;
priv->ctr_writable = ~0x10; priv->ctr_writable = ~0x10;
priv->ecr = 0; priv->ecr = 0;
...@@ -2154,59 +2148,37 @@ struct parport *parport_pc_probe_port (unsigned long int base, ...@@ -2154,59 +2148,37 @@ struct parport *parport_pc_probe_port (unsigned long int base,
priv->dma_buf = 0; priv->dma_buf = 0;
priv->dma_handle = 0; priv->dma_handle = 0;
priv->dev = dev; priv->dev = dev;
p->base = base; INIT_LIST_HEAD(&priv->list);
priv->port = p;
p->base_hi = base_hi; p->base_hi = base_hi;
p->irq = irq;
p->dma = dma;
p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
p->ops = ops;
p->private_data = priv; p->private_data = priv;
p->physport = p;
if (base_hi) { if (base_hi) {
ECR_res = request_region(base_hi, 3, fake_name); ECR_res = request_region(base_hi, 3, p->name);
if (ECR_res) if (ECR_res)
parport_ECR_present(p); parport_ECR_present(p);
} }
if (base != 0x3bc) { 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 (EPP_res)
if (!parport_EPP_supported(p)) if (!parport_EPP_supported(p))
parport_ECPEPP_supported(p); parport_ECPEPP_supported(p);
} }
if (!parport_SPP_supported (p)) if (!parport_SPP_supported (p))
/* No port. */ /* No port. */
goto errout; goto out5;
if (priv->ecr) if (priv->ecr)
parport_ECPPS2_supported(p); parport_ECPPS2_supported(p);
else 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->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); printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
if (p->base_hi && priv->ecr) if (p->base_hi && priv->ecr)
printk(" (0x%lx)", p->base_hi); printk(" (0x%lx)", p->base_hi);
p->irq = irq;
p->dma = dma;
if (p->irq == PARPORT_IRQ_AUTO) { if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE; p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p); parport_irq_probe(p);
...@@ -2269,7 +2241,6 @@ struct parport *parport_pc_probe_port (unsigned long int base, ...@@ -2269,7 +2241,6 @@ struct parport *parport_pc_probe_port (unsigned long int base,
printk("]\n"); printk("]\n");
if (probedirq != PARPORT_IRQ_NONE) if (probedirq != PARPORT_IRQ_NONE)
printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
parport_proc_register(p);
/* If No ECP release the ports grabbed above. */ /* If No ECP release the ports grabbed above. */
if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) { if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) {
...@@ -2330,28 +2301,40 @@ struct parport *parport_pc_probe_port (unsigned long int base, ...@@ -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 /* Now that we've told the sharing engine about the port, and
found out its characteristics, let the high-level drivers found out its characteristics, let the high-level drivers
know about it. */ know about it. */
spin_lock(&ports_lock);
list_add(&priv->list, &ports_list);
spin_unlock(&ports_lock);
parport_announce_port (p); parport_announce_port (p);
return p; return p;
errout: out5:
release_region(p->base, 3);
if (ECR_res) if (ECR_res)
release_region(base_hi, 3); release_region(base_hi, 3);
if (EPP_res) if (EPP_res)
release_region(base+0x3, 5); release_region(base+0x3, 5);
release_region(base, 3);
out4:
parport_put_port(p);
out3:
kfree (priv); kfree (priv);
out2:
kfree (ops); kfree (ops);
out1:
return NULL; return NULL;
} }
EXPORT_SYMBOL (parport_pc_probe_port);
void parport_pc_unregister_port (struct parport *p) void parport_pc_unregister_port (struct parport *p)
{ {
#ifdef CONFIG_PARPORT_PC_FIFO
struct parport_pc_private *priv = p->private_data; struct parport_pc_private *priv = p->private_data;
#endif /* CONFIG_PARPORT_PC_FIFO */
struct parport_operations *ops = p->ops; 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) if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma); free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE) if (p->irq != PARPORT_IRQ_NONE)
...@@ -2361,7 +2344,6 @@ void parport_pc_unregister_port (struct parport *p) ...@@ -2361,7 +2344,6 @@ void parport_pc_unregister_port (struct parport *p)
release_region(p->base + 3, p->size - 3); release_region(p->base + 3, p->size - 3);
if (p->modes & PARPORT_MODE_ECP) if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3); release_region(p->base_hi, 3);
parport_proc_unregister(p);
#ifdef CONFIG_PARPORT_PC_FIFO #ifdef CONFIG_PARPORT_PC_FIFO
if (priv->dma_buf) if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE, pci_free_consistent(priv->dev, PAGE_SIZE,
...@@ -2369,10 +2351,12 @@ void parport_pc_unregister_port (struct parport *p) ...@@ -2369,10 +2351,12 @@ void parport_pc_unregister_port (struct parport *p)
priv->dma_handle); priv->dma_handle);
#endif /* CONFIG_PARPORT_PC_FIFO */ #endif /* CONFIG_PARPORT_PC_FIFO */
kfree (p->private_data); kfree (p->private_data);
parport_unregister_port(p); parport_put_port(p);
kfree (ops); /* hope no-one cached it */ kfree (ops); /* hope no-one cached it */
} }
EXPORT_SYMBOL (parport_pc_unregister_port);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
/* ITE support maintained by Rich Liu <richliu@poorman.org> */ /* ITE support maintained by Rich Liu <richliu@poorman.org> */
...@@ -2931,45 +2915,57 @@ static int __init parport_pc_find_ports (int autoirq, int autodma) ...@@ -2931,45 +2915,57 @@ static int __init parport_pc_find_ports (int autoirq, int autodma)
return count; return count;
} }
int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma) /*
{ * Piles of crap below pretend to be a parser for module and kernel
int count = 0, i = 0; * parameters. Say "thank you" to whoever had come up with that
/* try to activate any PnP parports first */ * syntax and keep in mind that code below is a cleaned up version.
pnp_register_driver(&parport_pc_pnp_driver); */
if (io && *io) { static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
/* Only probe the ports we were given. */ static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] =
user_specified = 1; { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
do { static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
if ((*io_hi) == PARPORT_IOHI_AUTO) static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
*io_hi = 0x400 + *io;
if (parport_pc_probe_port(*(io++), *(io_hi++), static int __init parport_parse_param(const char *s, int *val,
*(irq++), *(dma++), NULL)) int automatic, int none, int nofifo)
count++; {
} while (*io && (++i < PARPORT_PC_MAX_PORTS)); if (!s)
} else { return 0;
count += parport_pc_find_ports (irq[0], dma[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. */ static int __init parport_parse_dma(const char *dmastr, int *val)
EXPORT_SYMBOL (parport_pc_probe_port); {
EXPORT_SYMBOL (parport_pc_unregister_port); return parport_parse_param(dmastr, val, PARPORT_DMA_AUTO,
PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO);
}
#ifdef MODULE #ifdef MODULE
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; static const char *irq[PARPORT_PC_MAX_PORTS];
static int io_hi[PARPORT_PC_MAX_PORTS+1] = static const char *dma[PARPORT_PC_MAX_PORTS];
{ [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");
MODULE_PARM_DESC(io, "Base I/O address (SPP regs)"); MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i"); 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"); ...@@ -2985,22 +2981,22 @@ MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
MODULE_PARM(verbose_probing, "i"); MODULE_PARM(verbose_probing, "i");
#endif #endif
int init_module(void) static int __init parse_parport_params(void)
{ {
/* Work out how many ports we have, then get parport_share to parse
the irq values. */
unsigned int i; 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;
}
else {
/* The user can make us use any IRQs or DMAs we find. */
int val; int val;
if (irq[0] && !parport_parse_irqs (1, irq, &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;
}
if (!io[0]) {
/* The user can make us use any IRQs or DMAs we find. */
if (irq[0] && !parport_parse_irq(irq[0], &val))
switch (val) { switch (val) {
case PARPORT_IRQ_NONE: case PARPORT_IRQ_NONE:
case PARPORT_IRQ_AUTO: case PARPORT_IRQ_AUTO:
...@@ -3013,7 +3009,7 @@ int init_module(void) ...@@ -3013,7 +3009,7 @@ int init_module(void)
"to specify one\n"); "to specify one\n");
} }
if (dma[0] && !parport_parse_dmas (1, dma, &val)) if (dma[0] && !parport_parse_dma(dma[0], &val))
switch (val) { switch (val) {
case PARPORT_DMA_NONE: case PARPORT_DMA_NONE:
case PARPORT_DMA_AUTO: case PARPORT_DMA_AUTO:
...@@ -3026,29 +3022,144 @@ int init_module(void) ...@@ -3026,29 +3022,144 @@ int init_module(void)
"to specify one\n"); "to specify one\n");
} }
} }
return 0;
}
ret = !parport_pc_init (io, io_hi, irqval, dmaval); #else
if (ret && registered_parport)
pci_unregister_driver (&parport_pc_pci_driver); 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;
return ret; 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;
}
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. */ return io[0] == PARPORT_DISABLE;
struct parport *p = parport_enumerate(), *tmp; }
if (!user_specified) __setup ("parport=", parport_setup);
pci_unregister_driver (&parport_pc_pci_driver); #endif
/* "Parser" ends here */
while (p) { static int __init parport_pc_init(void)
tmp = p->next; {
if (p->modes & PARPORT_MODE_PCSPP) int count = 0;
parport_pc_unregister_port (p);
if (parse_parport_params())
return -EINVAL;
p = tmp; /* 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); pnp_unregister_driver (&parport_pc_pnp_driver);
return -ENODEV;
}
return 0;
} }
#endif
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);
}
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 = ...@@ -286,39 +286,49 @@ static struct parport_operations parport_sunbpp_ops =
.owner = THIS_MODULE, .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) static int __init init_one_port(struct sbus_dev *sdev)
{ {
struct parport *p; struct parport *p;
/* at least in theory there may be a "we don't dma" case */ /* at least in theory there may be a "we don't dma" case */
struct parport_operations *ops; struct parport_operations *ops;
unsigned long base; unsigned long base;
int irq, dma, err, size; int irq, dma, err = 0, size;
struct bpp_regs *regs; struct bpp_regs *regs;
unsigned char value_tcr; unsigned char value_tcr;
Node *node;
dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); 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]; irq = sdev->irqs[0];
base = sbus_ioremap(&sdev->resource[0], 0, base = sbus_ioremap(&sdev->resource[0], 0,
sdev->reg_addrs[0].reg_size, sdev->reg_addrs[0].reg_size,
"sunbpp"); "sunbpp");
if (!base)
goto out1;
size = sdev->reg_addrs[0].reg_size; size = sdev->reg_addrs[0].reg_size;
dma = PARPORT_DMA_NONE; dma = PARPORT_DMA_NONE;
dprintk(("alloc(ppops), ")); dprintk(("alloc(ppops), "));
ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
if (!ops) { if (!ops)
sbus_iounmap(base, size); goto out2;
return 0;
}
memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
dprintk(("register_port\n")); dprintk(("register_port\n"));
if (!(p = parport_register_port(base, irq, dma, ops))) { if (!(p = parport_register_port(base, irq, dma, ops)))
kfree(ops); goto out3;
sbus_iounmap(base, size);
return 0;
}
p->size = size; p->size = size;
...@@ -327,14 +337,10 @@ static int __init init_one_port(struct sbus_dev *sdev) ...@@ -327,14 +337,10 @@ static int __init init_one_port(struct sbus_dev *sdev)
if ((err = request_irq(p->irq, parport_sunbpp_interrupt, if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
SA_SHIRQ, p->name, p)) != 0) { SA_SHIRQ, p->name, p)) != 0) {
dprintk(("ERROR %d\n", err)); dprintk(("ERROR %d\n", err));
parport_unregister_port(p); goto out4;
kfree(ops); }
sbus_iounmap(base, size);
return err;
} else {
dprintk(("OK\n")); dprintk(("OK\n"));
parport_sunbpp_enable_irq(p); parport_sunbpp_enable_irq(p);
}
regs = (struct bpp_regs *)p->base; regs = (struct bpp_regs *)p->base;
dprintk((KERN_DEBUG "forward\n")); dprintk((KERN_DEBUG "forward\n"));
...@@ -343,17 +349,25 @@ static int __init init_one_port(struct sbus_dev *sdev) ...@@ -343,17 +349,25 @@ static int __init init_one_port(struct sbus_dev *sdev)
sbus_writeb(value_tcr, &regs->p_tcr); sbus_writeb(value_tcr, &regs->p_tcr);
printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); 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); parport_announce_port (p);
return 1; return 1;
out4:
parport_put_port(p);
out3:
kfree(ops);
out2:
sbus_iounmap(base, size);
out1:
kfree(node);
out0:
return err;
} }
#ifdef MODULE static int __init parport_sunbpp_init(void)
int init_module(void)
#else
int __init parport_sunbpp_init(void)
#endif
{ {
struct sbus_bus *sbus; struct sbus_bus *sbus;
struct sbus_dev *sdev; struct sbus_dev *sdev;
...@@ -368,34 +382,30 @@ int __init parport_sunbpp_init(void) ...@@ -368,34 +382,30 @@ int __init parport_sunbpp_init(void)
return count ? 0 : -ENODEV; return count ? 0 : -ENODEV;
} }
#ifdef MODULE static void __exit parport_sunbpp_exit(void)
MODULE_AUTHOR("Derrick J Brashear");
MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
void
cleanup_module(void)
{ {
struct parport *p = parport_enumerate(); while (!list_empty(port_list)) {
Node *node = list_entry(port_list.next, Node, list);
while (p) { struct parport *p = node->port;
struct parport *next = p->next;
if (1/*p->modes & PARPORT_MODE_PCSPP*/) {
struct parport_operations *ops = p->ops; struct parport_operations *ops = p->ops;
parport_remove_port(p);
if (p->irq != PARPORT_IRQ_NONE) { if (p->irq != PARPORT_IRQ_NONE) {
parport_sunbpp_disable_irq(p); parport_sunbpp_disable_irq(p);
free_irq(p->irq, p); free_irq(p->irq, p);
} }
sbus_iounmap(p->base, p->size); sbus_iounmap(p->base, p->size);
parport_proc_unregister(p); parport_put_port(p);
parport_unregister_port(p);
kfree (ops); kfree (ops);
} list_del(&node->list);
p = next; 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_LICENSE("GPL");
module_init(parport_sunbpp_init)
module_exit(parport_sunbpp_exit)
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Philip Blundell <Philip.Blundell@pobox.com> * Philip Blundell <Philip.Blundell@pobox.com>
*/ */
#include <linux/module.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -212,3 +213,4 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len) ...@@ -212,3 +213,4 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
parport_close (dev); parport_close (dev);
return retval; return retval;
} }
EXPORT_SYMBOL(parport_device_id);
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -479,21 +481,20 @@ int parport_device_proc_unregister(struct pardevice *device) ...@@ -479,21 +481,20 @@ int parport_device_proc_unregister(struct pardevice *device)
return 0; return 0;
} }
int parport_default_proc_register(void) static int __init parport_default_proc_register(void)
{ {
parport_default_sysctl_table.sysctl_header = parport_default_sysctl_table.sysctl_header =
register_sysctl_table(parport_default_sysctl_table.dev_dir, 0); register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
return 0; return 0;
} }
int parport_default_proc_unregister(void) static void __exit parport_default_proc_unregister(void)
{ {
if (parport_default_sysctl_table.sysctl_header) { if (parport_default_sysctl_table.sysctl_header) {
unregister_sysctl_table(parport_default_sysctl_table. unregister_sysctl_table(parport_default_sysctl_table.
sysctl_header); sysctl_header);
parport_default_sysctl_table.sysctl_header = NULL; parport_default_sysctl_table.sysctl_header = NULL;
} }
return 0;
} }
#else /* no sysctl or no procfs*/ #else /* no sysctl or no procfs*/
...@@ -518,13 +519,19 @@ int parport_device_proc_unregister(struct pardevice *device) ...@@ -518,13 +519,19 @@ int parport_device_proc_unregister(struct pardevice *device)
return 0; return 0;
} }
int parport_default_proc_register (void) static int __init parport_default_proc_register (void)
{ {
return 0; return 0;
} }
int parport_default_proc_unregister (void) static void __exit parport_default_proc_unregister (void)
{ {
return 0; return 0;
} }
#endif #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 @@ ...@@ -41,14 +41,14 @@
unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE; unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
int parport_default_spintime = DEFAULT_SPIN_TIME; 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; static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
/* list of all allocated ports, sorted by ->number */ /* list of all allocated ports, sorted by ->number */
static LIST_HEAD(all_ports); static LIST_HEAD(all_ports);
static spinlock_t full_list_lock = SPIN_LOCK_UNLOCKED; 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); static DECLARE_MUTEX(registration_lock);
...@@ -105,16 +105,16 @@ static void attach_driver_chain(struct parport *port) ...@@ -105,16 +105,16 @@ static void attach_driver_chain(struct parport *port)
{ {
/* caller has exclusive registration_lock */ /* caller has exclusive registration_lock */
struct parport_driver *drv; struct parport_driver *drv;
for (drv = driver_chain; drv; drv = drv->next) list_for_each_entry(drv, &drivers, list)
drv->attach(port); drv->attach(port);
} }
/* Call detach(port) for each registered driver. */ /* Call detach(port) for each registered driver. */
static void detach_driver_chain(struct parport *port) static void detach_driver_chain(struct parport *port)
{ {
/* caller has exclusive registration_lock */
struct parport_driver *drv; 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); drv->detach (port);
} }
...@@ -155,22 +155,13 @@ int parport_register_driver (struct parport_driver *drv) ...@@ -155,22 +155,13 @@ int parport_register_driver (struct parport_driver *drv)
{ {
struct parport *port; struct parport *port;
if (!portlist) if (list_empty(&portlist))
get_lowlevel_driver (); 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); down(&registration_lock);
for (port = portlist; port; port = port->next) list_for_each_entry(port, &portlist, list)
drv->attach(port); drv->attach(port);
drv->next = driver_chain; list_add(&drv->list, &drivers);
driver_chain = drv;
up(&registration_lock); up(&registration_lock);
return 0; return 0;
...@@ -193,33 +184,14 @@ int parport_register_driver (struct parport_driver *drv) ...@@ -193,33 +184,14 @@ int parport_register_driver (struct parport_driver *drv)
* finished by the time this function returns. * 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;
down(&registration_lock);
drv = driver_chain;
while (drv) {
if (drv == arg) {
struct parport *port; struct parport *port;
if (olddrv) down(&registration_lock);
olddrv->next = drv->next; list_del_init(&drv->list);
else list_for_each_entry(port, &portlist, list)
driver_chain = drv->next; drv->detach(port);
/* 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;
}
up(&registration_lock); up(&registration_lock);
} }
...@@ -277,28 +249,6 @@ void parport_put_port (struct parport *port) ...@@ -277,28 +249,6 @@ void parport_put_port (struct parport *port)
return; 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 * parport_register_port - register a parallel port
* @base: base I/O address * @base: base I/O address
...@@ -322,7 +272,7 @@ struct parport *parport_enumerate(void) ...@@ -322,7 +272,7 @@ struct parport *parport_enumerate(void)
* parport_announce_port(). * parport_announce_port().
* *
* The @ops structure is allocated by the caller, and must not be * 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, * If there is no memory to allocate a new parport structure,
* this function will return %NULL. * this function will return %NULL.
...@@ -350,7 +300,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, ...@@ -350,7 +300,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
tmp->dma = dma; tmp->dma = dma;
tmp->muxport = tmp->daisy = tmp->muxsel = -1; tmp->muxport = tmp->daisy = tmp->muxsel = -1;
tmp->modes = 0; tmp->modes = 0;
tmp->next = NULL; INIT_LIST_HEAD(&tmp->list);
tmp->devices = tmp->cad = NULL; tmp->devices = tmp->cad = NULL;
tmp->flags = 0; tmp->flags = 0;
tmp->ops = ops; tmp->ops = ops;
...@@ -413,49 +363,36 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, ...@@ -413,49 +363,36 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
void parport_announce_port (struct parport *port) void parport_announce_port (struct parport *port)
{ {
int i;
#ifdef CONFIG_PARPORT_1284 #ifdef CONFIG_PARPORT_1284
/* Analyse the IEEE1284.3 topology of the port. */ /* Analyse the IEEE1284.3 topology of the port. */
if (parport_daisy_init (port) == 0) { parport_daisy_init(port);
/* 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);
}
#endif #endif
parport_proc_register(port);
down(&registration_lock); 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); spin_lock_irq(&parportlist_lock);
if (portlist_tail) list_add_tail(&port->list, &portlist);
portlist_tail->next = port; for (i = 1; i < 3; i++) {
portlist_tail = port; struct parport *slave = port->slaves[i-1];
if (!portlist) if (slave)
portlist = port; list_add_tail(&slave->list, &portlist);
}
spin_unlock_irq(&parportlist_lock); 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); 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); up(&registration_lock);
} }
/** /**
* parport_unregister_port - deregister a parallel port * parport_remove_port - deregister a parallel port
* @port: parallel port to deregister * @port: parallel port to deregister
* *
* When a parallel port driver is forcibly unloaded, or a * When a parallel port driver is forcibly unloaded, or a
...@@ -473,44 +410,46 @@ void parport_announce_port (struct parport *port) ...@@ -473,44 +410,46 @@ void parport_announce_port (struct parport *port)
* with @port as the parameter. * 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); down(&registration_lock);
port->ops = &dead_ops;
/* Spread the word. */ /* Spread the word. */
detach_driver_chain (port); detach_driver_chain (port);
#ifdef CONFIG_PARPORT_1284 #ifdef CONFIG_PARPORT_1284
/* Forget the IEEE1284.3 topology of the port. */ /* 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 #endif
port->ops = &dead_ops;
spin_lock(&parportlist_lock); spin_lock(&parportlist_lock);
list_del_init(&port->list);
/* We are protected from other people changing the list, but for (i = 1; i < 3; i++) {
* they can still see it (using parport_enumerate). So be struct parport *slave = port->slaves[i-1];
* careful about the order of writes.. */ if (slave)
if (portlist == port) { list_del_init(&slave->list);
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);
} }
spin_unlock(&parportlist_lock); spin_unlock(&parportlist_lock);
up(&registration_lock); up(&registration_lock);
/* Yes, parport_enumerate _is_ unsafe. Don't use it. */ parport_proc_unregister(port);
parport_put_port (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, ...@@ -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 /* We up our own module reference count, and that of the port
on which a device is to be registered, to ensure that on which a device is to be registered, to ensure that
neither of us gets unloaded while we sleep in (e.g.) neither of us gets unloaded while we sleep in (e.g.)
kmalloc. To be absolutely safe, we have to require that kmalloc.
our caller doesn't sleep in between parport_enumerate and */
parport_register_device.. */
if (!try_module_get(port->ops->owner)) { if (!try_module_get(port->ops->owner)) {
return NULL; return NULL;
} }
...@@ -751,11 +689,6 @@ void parport_unregister_device(struct pardevice *dev) ...@@ -751,11 +689,6 @@ void parport_unregister_device(struct pardevice *dev)
module_put(port->ops->owner); module_put(port->ops->owner);
parport_put_port (port); 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) ...@@ -774,15 +707,16 @@ struct parport *parport_find_number (int number)
{ {
struct parport *port, *result = NULL; struct parport *port, *result = NULL;
if (!portlist) if (list_empty(&portlist))
get_lowlevel_driver (); get_lowlevel_driver ();
spin_lock (&parportlist_lock); spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next) list_for_each_entry(port, &portlist, list) {
if (port->number == number) { if (port->number == number) {
result = parport_get_port (port); result = parport_get_port (port);
break; break;
} }
}
spin_unlock (&parportlist_lock); spin_unlock (&parportlist_lock);
return result; return result;
} }
...@@ -803,15 +737,16 @@ struct parport *parport_find_base (unsigned long base) ...@@ -803,15 +737,16 @@ struct parport *parport_find_base (unsigned long base)
{ {
struct parport *port, *result = NULL; struct parport *port, *result = NULL;
if (!portlist) if (list_empty(&portlist))
get_lowlevel_driver (); get_lowlevel_driver ();
spin_lock (&parportlist_lock); spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next) list_for_each_entry(port, &portlist, list) {
if (port->base == base) { if (port->base == base) {
result = parport_get_port (port); result = parport_get_port (port);
break; break;
} }
}
spin_unlock (&parportlist_lock); spin_unlock (&parportlist_lock);
return result; return result;
} }
...@@ -1060,41 +995,21 @@ void parport_release(struct pardevice *dev) ...@@ -1060,41 +995,21 @@ void parport_release(struct pardevice *dev)
} }
} }
static int parport_parse_params (int nports, const char *str[], int val[], /* Exported symbols for modules. */
int automatic, int none, int nofifo)
{ EXPORT_SYMBOL(parport_claim);
unsigned int i; EXPORT_SYMBOL(parport_claim_or_block);
for (i = 0; i < nports && str[i]; i++) { EXPORT_SYMBOL(parport_release);
if (!strncmp(str[i], "auto", 4)) EXPORT_SYMBOL(parport_register_port);
val[i] = automatic; EXPORT_SYMBOL(parport_announce_port);
else if (!strncmp(str[i], "none", 4)) EXPORT_SYMBOL(parport_remove_port);
val[i] = none; EXPORT_SYMBOL(parport_register_driver);
else if (nofifo && !strncmp(str[i], "nofifo", 4)) EXPORT_SYMBOL(parport_unregister_driver);
val[i] = nofifo; EXPORT_SYMBOL(parport_register_device);
else { EXPORT_SYMBOL(parport_unregister_device);
char *ep; EXPORT_SYMBOL(parport_get_port);
unsigned long r = simple_strtoul(str[i], &ep, 0); EXPORT_SYMBOL(parport_put_port);
if (ep != str[i]) EXPORT_SYMBOL(parport_find_number);
val[i] = r; EXPORT_SYMBOL(parport_find_base);
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);
}
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"); MODULE_LICENSE("GPL");
...@@ -592,7 +592,6 @@ static int uss720_probe(struct usb_interface *intf, ...@@ -592,7 +592,6 @@ static int uss720_probe(struct usb_interface *intf,
goto probe_abort_port; goto probe_abort_port;
} }
#endif #endif
parport_proc_register(pp);
parport_announce_port(pp); parport_announce_port(pp);
usb_set_intfdata (intf, pp); usb_set_intfdata (intf, pp);
...@@ -600,7 +599,7 @@ static int uss720_probe(struct usb_interface *intf, ...@@ -600,7 +599,7 @@ static int uss720_probe(struct usb_interface *intf,
#if 0 #if 0
probe_abort_port: probe_abort_port:
parport_unregister_port(pp); parport_put_port(pp);
#endif #endif
probe_abort: probe_abort:
kfree(priv); kfree(priv);
...@@ -615,12 +614,12 @@ static void uss720_disconnect(struct usb_interface *intf) ...@@ -615,12 +614,12 @@ static void uss720_disconnect(struct usb_interface *intf)
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (pp) { if (pp) {
priv = pp->private_data; priv = pp->private_data;
parport_remove_port(pp);
#if 0 #if 0
usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe); usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
#endif #endif
priv->usbdev = NULL; priv->usbdev = NULL;
parport_proc_unregister(pp); parport_put_port(pp);
parport_unregister_port(pp);
kfree(priv); kfree(priv);
} }
} }
......
...@@ -294,7 +294,7 @@ struct parport { ...@@ -294,7 +294,7 @@ struct parport {
struct pardevice *waithead; struct pardevice *waithead;
struct pardevice *waittail; struct pardevice *waittail;
struct parport *next; struct list_head list;
unsigned int flags; unsigned int flags;
void *sysctl_table; void *sysctl_table;
...@@ -313,6 +313,7 @@ struct parport { ...@@ -313,6 +313,7 @@ struct parport {
atomic_t ref_count; atomic_t ref_count;
struct list_head full_list; struct list_head full_list;
struct parport *slaves[3];
}; };
#define DEFAULT_SPIN_TIME 500 /* us */ #define DEFAULT_SPIN_TIME 500 /* us */
...@@ -321,7 +322,7 @@ struct parport_driver { ...@@ -321,7 +322,7 @@ struct parport_driver {
const char *name; const char *name;
void (*attach) (struct parport *); void (*attach) (struct parport *);
void (*detach) (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 /* 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, ...@@ -339,12 +340,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
void parport_announce_port (struct parport *port); void parport_announce_port (struct parport *port);
/* Unregister a port. */ /* Unregister a port. */
extern void parport_unregister_port(struct parport *port); extern void parport_remove_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);
/* Register a new high-level driver. */ /* Register a new high-level driver. */
extern int parport_register_driver (struct parport_driver *); extern int parport_register_driver (struct parport_driver *);
...@@ -451,9 +447,6 @@ static __inline__ int parport_yield_blocking(struct pardevice *dev) ...@@ -451,9 +447,6 @@ static __inline__ int parport_yield_blocking(struct pardevice *dev)
#define PARPORT_FLAG_EXCL (1<<1) /* EXCL driver registered. */ #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 */ /* IEEE1284 functions */
extern void parport_ieee1284_interrupt (int, void *, struct pt_regs *); extern void parport_ieee1284_interrupt (int, void *, struct pt_regs *);
extern int parport_negotiate (struct parport *, int mode); extern int parport_negotiate (struct parport *, int mode);
...@@ -538,8 +531,6 @@ extern int parport_proc_register(struct parport *pp); ...@@ -538,8 +531,6 @@ extern int parport_proc_register(struct parport *pp);
extern int parport_proc_unregister(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_register(struct pardevice *device);
extern int parport_device_proc_unregister(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 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) #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 { ...@@ -39,6 +39,8 @@ struct parport_pc_private {
char *dma_buf; char *dma_buf;
dma_addr_t dma_handle; dma_addr_t dma_handle;
struct pci_dev *dev; struct pci_dev *dev;
struct list_head list;
struct parport *port;
}; };
static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) 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