Philip Blundell (Philip.Blundell@pobox.com)
Sat, 04 Apr 1998 19:52:55 +0100
Hi.
Here's a patch I made to change the irq-related behaviour of parport slightly.
Please give it a try.
The current thinking is that parport should default to polled operation unless
you explicitly ask for irqs to be enabled. If your hardware supports
autoprobing then you can do this with `irq=auto' (for modules) and
`parport=0x278,auto' on the command line. If not then you have to give the
actual IRQ number.
BTW, some recent change seems to have broken things slightly for me. If I set
my port to ECP mode and load parport_pc it detects it OK; if I then unload and
reload the module it fails to find the port at all. Has anybody else seen
this?
p.
diff -u --recursive --new-file /home/phil/clean/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- /home/phil/clean/linux/Documentation/parport.txt Sat Nov 29 18:33:18 1997
+++ linux/Documentation/parport.txt Sat Apr 4 18:51:45 1998
@@ -5,11 +5,15 @@
You can pass parameters to the parport code to override its automatic
detection of your hardware. This is particularly useful if you want
to use IRQs, since in general these can't be autoprobed successfully.
+By default IRQs are not used even if they _can_ be probed. This is
+because there are a lot of people using the same IRQ for their
+parallel port and a sound card or network card.
The parport code is split into two parts: generic (which deals with
port-sharing) and architecture-dependent (which deals with actually
using the port).
+
Parport as modules
==================
@@ -20,25 +24,13 @@
to load the generic parport code. You then must load the
architecture-dependent code with (for example):
- # insmod parport_pc.o io=0x378,0x278 irq=7,5
-
-to tell the parport code that you want two PC-style ports, one at
-0x378 using IRQ 7, and one at 0x278 using IRQ 5. Currently, PC-style
-(parport_pc) and ARC onboard (parport_arc) parallel ports are
-supported.
-
-Kerneld
--------
+ # insmod parport_pc.o io=0x3bc,0x378,0x278 irq=none,7,auto
-If you use kerneld, you will find it useful to edit /etc/conf.modules.
-Here is an example of the lines that need to be added:
+to tell the parport code that you want three PC-style ports, one at
+0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
+auto-detected IRQ. Currently, PC-style (parport_pc) and Sun Ultra/AX
+(parport_ax) hardware is supported; more is in the works.
- alias parport_lowlevel parport_pc
- options parport_pc io=0x378,0x278 irq=7,5
-
-Kerneld, in conjunction with parport, will automatically load
-parport_pc whenever a parallel port device driver (such as lp) is
-loaded.
Parport probe [optional]
-------------
@@ -53,8 +45,8 @@
parport0: Printer, BJC-210 (Canon)
-(If you are using kerneld and have configured parport_probe as a
-module, this will just happen.)
+(If you are using kmod and have configured parport_probe as a module,
+this will just happen.)
Parport, but not as modules
@@ -64,7 +56,7 @@
kernel boot parameters to get the same effect. Add something like the
following to your LILO command line:
- parport=0x378,7 parport=0x278,5
+ parport=0x3bc parport=0x378,7 parport=0x278,auto
You can have many `parport=...' statements, one for each port you want
to add. Adding `parport=0' to the kernel command-line will disable
@@ -121,7 +113,7 @@
Also:
- * If you selected the device autoprobe at compile time, you can say
+ * If you selected the IEEE-1284 autoprobe at compile time, you can say
`lp=auto' on the kernel command line, and lp will create devices
only for those ports that seem to have printers attached.
@@ -129,10 +121,7 @@
the command line, or with `insmod plip timid=1' when using modules,
it will avoid any ports that seem to be in use by other devices.
- * If your BIOS allows you to engage "ECP mode", you may find that
- your port's IRQ can be autoprobed, without having to specify any
- parameters.
-
+ * IRQ autoprobing works only for a few port types at the moment.
--
Philip.Blundell@pobox.com
diff -u --recursive --new-file /home/phil/clean/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c
--- /home/phil/clean/linux/drivers/misc/parport_init.c Sat Apr 4 15:51:38 1998
+++ linux/drivers/misc/parport_init.c Sat Apr 4 18:27:32 1998
@@ -20,7 +20,7 @@
#ifndef MODULE
static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
-static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_NONE };
+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 *irq, int *dma);
@@ -36,20 +36,38 @@
return;
}
if (parport_setup_ptr < PARPORT_MAX) {
- io[parport_setup_ptr] = ints[1];
- if (ints[0]>1) {
- irq[parport_setup_ptr] = ints[2];
- if (ints[0]>2) dma[parport_setup_ptr] = ints[3];
+ char *sep;
+ io[parport_setup_ptr] = simple_strtoul(str, NULL, 0);
+ if ((sep = strchr(str, ',')) == NULL) goto done;
+ str = sep+1;
+ if (!strncmp(str, "none", 4))
+ irq[parport_setup_ptr] = PARPORT_IRQ_NONE;
+ else if (!strncmp(str, "auto", 4))
+ irq[parport_setup_ptr] = PARPORT_IRQ_AUTO;
+ else {
+ char *ep;
+ irq[parport_setup_ptr] = simple_strtoul(str, &ep, NULL);
+ if (ep == str) {
+ printk("parport: bad irq `%s'\n", str);
+ return;
+ }
}
- parport_setup_ptr++;
- } else {
- printk(KERN_ERR "parport=0x%x", ints[1]);
- if (ints[0]>1) {
- printk(",%d", ints[2]);
- if (ints[0]>2) printk(",%d", ints[3]);
+ if ((sep = strchr(str, ',')) == NULL) goto done;
+ str = sep+1;
+ if (!strncmp(str, "auto", 4))
+ dma[parport_setup_ptr] = PARPORT_DMA_AUTO;
+ else {
+ char *ep;
+ dma[parport_setup_ptr] = simple_strtoul(str, &ep, NULL);
+ if (ep == str) {
+ printk("parport: bad dma `%s'\n", str);
+ return;
+ }
}
- printk(" ignored, too many ports.\n");
- }
+ done:
+ parport_setup_ptr++;
+ } else
+ printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
}
#endif
@@ -100,6 +118,7 @@
EXPORT_SYMBOL(parport_proc_register);
EXPORT_SYMBOL(parport_proc_unregister);
EXPORT_SYMBOL(parport_probe_hook);
+EXPORT_SYMBOL(parport_parse_irqs);
void inc_parport_count(void)
{
diff -u --recursive --new-file /home/phil/clean/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- /home/phil/clean/linux/drivers/misc/parport_pc.c Sat Apr 4 15:52:45 1998
+++ linux/drivers/misc/parport_pc.c Sat Apr 4 19:22:44 1998
@@ -846,6 +846,7 @@
static int probe_one_port(unsigned long int base, int irq, int dma)
{
struct parport tmpport, *p;
+ int probedirq = PARPORT_IRQ_NONE;
if (check_region(base, 3)) return 0;
tmpport.base = base;
tmpport.ops = &parport_pc_ops;
@@ -869,6 +870,11 @@
if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p);
+ } else if (p->irq == PARPORT_IRQ_PROBEONLY) {
+ p->irq = PARPORT_IRQ_NONE;
+ parport_irq_probe(p);
+ probedirq = p->irq;
+ p->irq = PARPORT_IRQ_NONE;
}
if (p->irq != PARPORT_IRQ_NONE)
printk(", irq %d", p->irq);
@@ -890,6 +896,8 @@
}
#undef printmode
printk("]\n");
+ if (probedirq != PARPORT_IRQ_NONE)
+ printk("%s: detected irq %d; use procfs to enable interrupt-driven operation.\n", p->name, probedirq);
parport_proc_register(p);
p->flags |= PARPORT_FLAG_COMA;
@@ -913,9 +921,9 @@
} while (*io && (++i < PARPORT_PC_MAX_PORTS));
} else {
/* Probe all the likely ports. */
- count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
- count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
- count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
+ count += probe_one_port(0x3bc, PARPORT_IRQ_PROBEONLY, PARPORT_DMA_AUTO);
+ count += probe_one_port(0x378, PARPORT_IRQ_PROBEONLY, PARPORT_DMA_AUTO);
+ count += probe_one_port(0x278, PARPORT_IRQ_PROBEONLY, PARPORT_DMA_AUTO);
}
/* Give any attached devices a chance to gather their thoughts */
@@ -929,14 +937,21 @@
#ifdef MODULE
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
-static int irq[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
+static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
+static char *irq = NULL;
MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
int init_module(void)
{
- return (parport_pc_init(io, irq, dma)?0:1);
+ /* Work out how many ports we have, then get parport_share to parse
+ the irq values. */
+ unsigned int i;
+ for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
+ parport_parse_irqs(i, irq, irqval);
+
+ return (parport_pc_init(io, irqval, dma)?0:1);
}
void cleanup_module(void)
diff -u --recursive --new-file /home/phil/clean/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- /home/phil/clean/linux/drivers/misc/parport_share.c Sat Apr 4 15:52:08 1998
+++ linux/drivers/misc/parport_share.c Sat Apr 4 18:29:00 1998
@@ -441,3 +441,26 @@
pd->wakeup(pd->private);
}
}
+
+void parport_parse_irqs(int nports, const char *irqstr, int irqval[])
+{
+ unsigned int i;
+ for (i = 0; i < nports && irqstr; i++) {
+ if (!strncmp(irqstr, "auto", 4))
+ irqval[i] = PARPORT_IRQ_AUTO;
+ else if (!strncmp(irqstr, "none", 4))
+ irqval[i] = PARPORT_IRQ_NONE;
+ else {
+ char *ep;
+ unsigned long r = simple_strtoul(irqstr, &ep, 0);
+ if (ep != irqstr)
+ irqval[i] = r;
+ else {
+ printk("parport: bad irq specifier `%s'\n", irqstr);
+ return;
+ }
+ }
+ irqstr = strchr(irqstr, ',');
+ if (irqstr) irqstr++;
+ }
+}
diff -u --recursive --new-file /home/phil/clean/linux/include/linux/parport.h linux/include/linux/parport.h
--- /home/phil/clean/linux/include/linux/parport.h Sat Apr 4 15:50:51 1998
+++ linux/include/linux/parport.h Sat Apr 4 18:52:59 1998
@@ -14,6 +14,7 @@
#define PARPORT_IRQ_AUTO -2
#define PARPORT_DMA_AUTO -2
#define PARPORT_DISABLE -2
+#define PARPORT_IRQ_PROBEONLY -3
#define PARPORT_CONTROL_STROBE 0x1
#define PARPORT_CONTROL_AUTOFD 0x2
@@ -291,6 +292,7 @@
#define PARPORT_FLAG_COMA 1
+extern void parport_parse_irqs(int, const char *, int irqval[]);
extern int parport_ieee1284_nibble_mode_ok(struct parport *, unsigned char);
extern int parport_wait_peripheral(struct parport *, unsigned char, unsigned
char);
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2.0b3 on Wed 30 Dec 1998 - 10:17:35 EST