patch-2.1.96 linux/drivers/misc/parport_pc.c
Next file: linux/drivers/misc/parport_share.c
Previous file: linux/drivers/misc/parport_init.c
Back to the patch index
Back to the overall index
- Lines: 256
- Date:
Mon Apr 13 14:39:59 1998
- Orig file:
v2.1.95/linux/drivers/misc/parport_pc.c
- Orig date:
Fri Apr 10 13:03:48 1998
diff -u --recursive --new-file v2.1.95/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
@@ -36,7 +36,6 @@
#include <asm/ptrace.h>
#include <asm/io.h>
-#include <asm/dma.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -163,9 +162,9 @@
int parport_pc_claim_resources(struct parport *p)
{
- /* FIXME check that resources are free */
+ int err;
if (p->irq != PARPORT_IRQ_NONE)
- request_irq(p->irq, parport_pc_null_intr_func, 0, p->name, NULL);
+ if ((err = request_irq(p->irq, parport_pc_null_intr_func, 0, p->name, NULL)) != 0) return err;
request_region(p->base, p->size, p->name);
if (p->modes & PARPORT_MODE_PCECR)
request_region(p->base+0x400, 3, p->name);
@@ -276,159 +275,6 @@
parport_pc_dec_use_count
};
-/* --- DMA detection -------------------------------------- */
-
-/*
- * Prepare DMA channels from 0-8 to transmit towards buffer
- */
-static int parport_prepare_dma(char *buff, int size)
-{
- int tmp = 0;
- int i,retv;
-
- for (i = 0; i < 8; i++) {
- retv = request_dma(i, "probe");
- if (retv)
- continue;
- tmp |= 1 << i;
-
- cli();
- disable_dma(i);
- clear_dma_ff(i);
- set_dma_addr(i, virt_to_bus(buff));
- set_dma_count(i, size);
- set_dma_mode(i, DMA_MODE_READ);
- sti();
- }
-
- return tmp;
-}
-
-/*
- * Activate all DMA channels passed in dma
- */
-static int parport_enable_dma(int dma)
-{
- int i;
-
- for (i = 0; i < 8; i++)
- if (dma & (1 << i)) {
- cli();
- enable_dma(i);
- sti();
- }
-
- return dma;
-}
-
-static int parport_detect_dma_transfer(int dma, int size)
-{
- int i,n,retv;
- int count=0;
-
- retv = PARPORT_DMA_NONE;
- for (i = 0; i < 8; i++)
- if (dma & (1 << i)) {
- disable_dma(i);
- clear_dma_ff(i);
- n = get_dma_residue(i);
- if (n != size) {
- retv = i;
- if (count > 0) {
- retv = PARPORT_DMA_NONE; /* Multiple DMA's */
- printk(KERN_ERR "parport: multiple DMA detected. Huh?\n");
- }
- count++;
- }
- free_dma(i);
- }
-
- return retv;
-}
-
-/* Only if supports ECP mode */
-static int programmable_dma_support(struct parport *pb)
-{
- unsigned char dma, oldstate = parport_pc_read_econtrol(pb);
-
- parport_pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
-
- dma = parport_pc_read_configb(pb) & 0x07;
-
- parport_pc_write_econtrol(pb, oldstate);
-
- if (dma == 0 || dma == 4) /* Jumper selection */
- return PARPORT_DMA_NONE;
- else
- return dma;
-}
-
-/* Only called if port supports ECP mode.
- *
- * The only restriction on DMA channels is that it has to be
- * between 0 to 7 (inclusive). Used only in an ECP mode, DMAs are
- * considered a shared resource and hence they should be registered
- * when needed and then immediately unregistered.
- *
- * DMA autoprobes for ECP mode are known not to work for some
- * main board BIOS configs. I had to remove everything from the
- * port, set the mode to SPP, reboot to DOS, set the mode to ECP,
- * and reboot again, then I got IRQ probes and DMA probes to work.
- * [Is the BIOS doing a device detection?]
- *
- * A value of PARPORT_DMA_NONE is allowed indicating no DMA support.
- *
- * if( 0 < DMA < 4 )
- * 1Byte DMA transfer
- * else // 4 < DMA < 8
- * 2Byte DMA transfer
- *
- */
-static int parport_dma_probe(struct parport *pb)
-{
- int dma,retv;
- unsigned char dsr,dsr_read;
- char *buff;
-
- retv = programmable_dma_support(pb);
- if (retv != PARPORT_DMA_NONE)
- return retv;
-
- if (!(buff = kmalloc(2048, GFP_KERNEL | GFP_DMA))) {
- printk(KERN_ERR "parport: memory squeeze\n");
- return PARPORT_DMA_NONE;
- }
-
- dsr = pb->ops->read_control(pb);
- dsr_read = (dsr & ~(0x20)) | 0x04; /* Direction == read */
-
- pb->ops->write_econtrol(pb, 0xc0); /* ECP MODE */
- pb->ops->write_control(pb, dsr_read );
- dma = parport_prepare_dma(buff, 1000);
- pb->ops->write_econtrol(pb, 0xd8); /* ECP FIFO + enable DMA */
- parport_enable_dma(dma);
- udelay(500); /* Give some for DMA tranfer */
- retv = parport_detect_dma_transfer(dma, 1000);
-
- /*
- * National Semiconductors only supports DMA tranfers
- * in ECP MODE
- */
- if (retv == PARPORT_DMA_NONE) {
- pb->ops->write_econtrol(pb, 0x60); /* ECP MODE */
- pb->ops->write_control(pb, dsr_read );
- dma=parport_prepare_dma(buff,1000);
- pb->ops->write_econtrol(pb, 0x68); /* ECP FIFO + enable DMA */
- parport_enable_dma(dma);
- udelay(500); /* Give some for DMA tranfer */
- retv = parport_detect_dma_transfer(dma, 1000);
- }
-
- kfree(buff);
-
- return retv;
-}
-
/* --- Mode detection ------------------------------------- */
/*
@@ -807,6 +653,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;
@@ -830,12 +677,16 @@
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);
if (p->dma == PARPORT_DMA_AUTO)
- p->dma = (p->modes & PARPORT_MODE_PCECP)?
- parport_dma_probe(p):PARPORT_DMA_NONE;
+ p->dma = PARPORT_DMA_NONE;
if (p->dma != PARPORT_DMA_NONE)
printk(", dma %d", p->dma);
printk(" [");
@@ -851,6 +702,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;
@@ -875,9 +728,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, irq[0], dma[0]);
+ count += probe_one_port(0x378, irq[0], dma[0]);
+ count += probe_one_port(0x278, irq[0], dma[0]);
}
/* Give any attached devices a chance to gather their thoughts */
@@ -890,15 +743,22 @@
#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 dma[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 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)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov