+++ /dev/null
-/* 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);
-
-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);
-
-int __init parport_init (void)
-{
- if (io[0] == PARPORT_DISABLE)
- return 1;
-#ifdef CONFIG_PARPORT_PC
- parport_pc_init(io, io_hi, irq, dma);
-#endif
- return 0;
-}
-
-__initcall(parport_init);
-
-#endif
return NULL;
}
+EXPORT_SYMBOL (parport_pc_probe_port);
+
void parport_pc_unregister_port (struct parport *p)
{
#ifdef CONFIG_PARPORT_PC_FIFO
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> */
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");
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:
"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:
"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;
- 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)
+{
+ return io[0] == PARPORT_DISABLE;
+}
+
+__setup ("parport=", parport_setup);
+#endif
+
+/* "Parser" ends here */
+
+static int __init parport_pc_init(void)
+{
+ int count = 0;
+
+ 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)
{
/* We ought to keep track of which ports are actually ours. */
struct parport *p = parport_enumerate(), *tmp;
- if (!user_specified)
+ if (registered_parport)
pci_unregister_driver (&parport_pc_pci_driver);
while (p) {
}
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)