patch-2.3.3 linux/drivers/misc/parport_pc.c

Next file: linux/drivers/net/cosa.c
Previous file: linux/drivers/misc/parport_init.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.2/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
@@ -36,6 +36,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -53,7 +54,7 @@
    than PARPORT_MAX (in <linux/parport.h>).  */
 #define PARPORT_PC_MAX_PORTS  8
 
-static int user_specified = 0;
+static int user_specified __initdata = 0;
 
 static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -62,27 +63,27 @@
 
 void parport_pc_write_epp(struct parport *p, unsigned char d)
 {
-	outb(d, p->base+EPPDATA);
+	outb(d, EPPDATA(p));
 }
 
 unsigned char parport_pc_read_epp(struct parport *p)
 {
-	return inb(p->base+EPPDATA);
+	return inb(EPPDATA(p));
 }
 
 void parport_pc_write_epp_addr(struct parport *p, unsigned char d)
 {
-	outb(d, p->base+EPPADDR);
+	outb(d, EPPADDR(p));
 }
 
 unsigned char parport_pc_read_epp_addr(struct parport *p)
 {
-	return inb(p->base+EPPADDR);
+	return inb(EPPADDR(p));
 }
 
 int parport_pc_check_epp_timeout(struct parport *p)
 {
-	if (!(inb(p->base+STATUS) & 1))
+	if (!(inb(STATUS(p)) & 1))
 		return 0;
 	parport_pc_epp_clear_timeout(p);
 	return 1;
@@ -90,24 +91,24 @@
 
 unsigned char parport_pc_read_configb(struct parport *p)
 {
-	return inb(p->base+CONFIGB);
+	return inb(CONFIGB(p));
 }
 
 void parport_pc_write_data(struct parport *p, unsigned char d)
 {
-	outb(d, p->base+DATA);
+	outb(d, DATA(p));
 }
 
 unsigned char parport_pc_read_data(struct parport *p)
 {
-	return inb(p->base+DATA);
+	return inb(DATA(p));
 }
 
 void parport_pc_write_control(struct parport *p, unsigned char d)
 {
 	struct parport_pc_private *priv = p->private_data;
 	priv->ctr = d;/* update soft copy */
-	outb(d, p->base+CONTROL);
+	outb(d, CONTROL(p));
 }
 
 unsigned char parport_pc_read_control(struct parport *p)
@@ -121,34 +122,34 @@
 	struct parport_pc_private *priv = p->private_data;
 	unsigned char ctr = priv->ctr;
 	ctr = (ctr & ~mask) ^ val;
-	outb (ctr, p->base+CONTROL);
+	outb (ctr, CONTROL(p));
 	return priv->ctr = ctr; /* update soft copy */
 }
 
 void parport_pc_write_status(struct parport *p, unsigned char d)
 {
-	outb(d, p->base+STATUS);
+	outb(d, STATUS(p));
 }
 
 unsigned char parport_pc_read_status(struct parport *p)
 {
-	return inb(p->base+STATUS);
+	return inb(STATUS(p));
 }
 
 void parport_pc_write_econtrol(struct parport *p, unsigned char d)
 {
-	outb(d, p->base+ECONTROL);
+	outb(d, ECONTROL(p));
 }
 
 unsigned char parport_pc_read_econtrol(struct parport *p)
 {
-	return inb(p->base+ECONTROL);
+	return inb(ECONTROL(p));
 }
 
 unsigned char parport_pc_frob_econtrol(struct parport *p, unsigned char mask,  unsigned char val)
 {
-	unsigned char old = inb(p->base+ECONTROL);
-	outb(((old & ~mask) ^ val), p->base+ECONTROL);
+	unsigned char old = inb(ECONTROL(p));
+	outb(((old & ~mask) ^ val), ECONTROL(p));
 	return old;
 }
 
@@ -159,12 +160,12 @@
 
 void parport_pc_write_fifo(struct parport *p, unsigned char v)
 {
-	outb (v, p->base+CONFIGA);
+	outb (v, CONFIGA(p));
 }
 
 unsigned char parport_pc_read_fifo(struct parport *p)
 {
-	return inb (p->base+CONFIGA);
+	return inb (CONFIGA(p));
 }
 
 void parport_pc_disable_irq(struct parport *p)
@@ -183,7 +184,7 @@
 		free_irq(p->irq, p);
 	release_region(p->base, p->size);
 	if (p->modes & PARPORT_MODE_PCECR)
-		release_region(p->base+0x400, 3);
+		release_region(p->base_hi, 3);
 }
 
 int parport_pc_claim_resources(struct parport *p)
@@ -195,7 +196,7 @@
 			return err;
 	request_region(p->base, p->size, p->name);
 	if (p->modes & PARPORT_MODE_PCECR)
-		request_region(p->base+0x400, 3, p->name);
+		request_region(p->base_hi, 3, p->name);
 	return 0;
 }
 
@@ -223,8 +224,8 @@
 {
 	size_t got = 0;
 	for (; got < length; got++) {
-		*((char*)buf)++ = inb (p->base+EPPDATA);
-		if (inb (p->base+STATUS) & 0x01)
+		*((char*)buf)++ = inb (EPPDATA(p));
+		if (inb (STATUS(p)) & 0x01)
 			break;
 	}
 	return got;
@@ -234,8 +235,8 @@
 {
 	size_t written = 0;
 	for (; written < length; written++) {
-		outb (*((char*)buf)++, p->base+EPPDATA);
-		if (inb (p->base+STATUS) & 0x01)
+		outb (*((char*)buf)++, EPPDATA(p));
+		if (inb (STATUS(p)) & 0x01)
 			break;
 	}
 	return written;
@@ -350,7 +351,7 @@
 /*
  * Checks for port existence, all ports support SPP MODE
  */
-static int parport_SPP_supported(struct parport *pb)
+static int __init parport_SPP_supported(struct parport *pb)
 {
 	unsigned char r, w;
 
@@ -370,11 +371,11 @@
 	 * allow reads, so read_control just returns a software
 	 * copy. Some ports _do_ allow reads, so bypass the software
 	 * copy here.  In addition, some bits aren't writable. */
-	r = inb (pb->base+CONTROL);
+	r = inb (CONTROL (pb));
 	if ((r & 0x3f) == w) {
 		w = 0xe;
 		parport_pc_write_control (pb, w);
-		r = inb (pb->base+CONTROL);
+		r = inb (CONTROL(pb));
 		parport_pc_write_control (pb, 0xc);
 		if ((r & 0x3f) == w)
 			return PARPORT_MODE_PCSPP;
@@ -425,7 +426,7 @@
  * We will write 0x2c to ECR and 0xcc to CTR since both of these
  * values are "safe" on the CTR since bits 6-7 of CTR are unused.
  */
-static int parport_ECR_present(struct parport *pb)
+static int __init parport_ECR_present(struct parport *pb)
 {
 	unsigned char r;
 
@@ -458,7 +459,7 @@
 	return 0;
 }
 
-static int parport_ECP_supported(struct parport *pb)
+static int __init parport_ECP_supported(struct parport *pb)
 {
 	int i;
 	unsigned char oecr;
@@ -493,7 +494,7 @@
  *	or writing a 1 to the bit (SMC, UMC, WinBond), others ???
  *	This bit is always high in non EPP modes.
  */
-static int parport_EPP_supported(struct parport *pb)
+static int __init parport_EPP_supported(struct parport *pb)
 {
 	/* If EPP timeout bit clear then EPP available */
 	if (!parport_pc_epp_clear_timeout(pb))
@@ -514,7 +515,7 @@
 	return 0;
 }
 
-static int parport_ECPEPP_supported(struct parport *pb)
+static int __init parport_ECPEPP_supported(struct parport *pb)
 {
 	int mode;
 	unsigned char oecr;
@@ -550,7 +551,7 @@
  * be misdetected here is rather academic. 
  */
 
-static int parport_PS2_supported(struct parport *pb)
+static int __init parport_PS2_supported(struct parport *pb)
 {
 	int ok = 0;
 	unsigned char octr = parport_pc_read_control(pb);
@@ -570,7 +571,7 @@
 	return ok?PARPORT_MODE_PCPS2:0;
 }
 
-static int parport_ECPPS2_supported(struct parport *pb)
+static int __init parport_ECPPS2_supported(struct parport *pb)
 {
 	int mode;
 	unsigned char oecr;
@@ -590,7 +591,7 @@
 /* --- IRQ detection -------------------------------------- */
 
 /* Only if supports ECP mode */
-static int programmable_irq_support(struct parport *pb)
+static int __init programmable_irq_support(struct parport *pb)
 {
 	int irq, intrLine;
 	unsigned char oecr = parport_pc_read_econtrol(pb);
@@ -607,7 +608,7 @@
 	return irq;
 }
 
-static int irq_probe_ECP(struct parport *pb)
+static int __init irq_probe_ECP(struct parport *pb)
 {
 	int irqs, i;
 
@@ -634,7 +635,7 @@
  * This detection seems that only works in National Semiconductors
  * This doesn't work in SMC, LGS, and Winbond 
  */
-static int irq_probe_EPP(struct parport *pb)
+static int __init irq_probe_EPP(struct parport *pb)
 {
 	int irqs;
 	unsigned char octr = parport_pc_read_control(pb);
@@ -675,7 +676,7 @@
 	return pb->irq;
 }
 
-static int irq_probe_SPP(struct parport *pb)
+static int __init irq_probe_SPP(struct parport *pb)
 {
 	int irqs;
 	unsigned char octr = parport_pc_read_control(pb);
@@ -723,7 +724,7 @@
  * When ECP is available we can autoprobe for IRQs.
  * NOTE: If we can autoprobe it, we can register the IRQ.
  */
-static int parport_irq_probe(struct parport *pb)
+static int __init parport_irq_probe(struct parport *pb)
 {
 	if (pb->modes & PARPORT_MODE_PCECR) {
 		pb->irq = programmable_irq_support(pb);
@@ -754,7 +755,9 @@
 
 /* --- Initialisation code -------------------------------- */
 
-static int probe_one_port(unsigned long int base, int irq, int dma)
+static int __init probe_one_port(unsigned long int base,
+				 unsigned long int base_hi,
+				 int irq, int dma)
 {
 	struct parport *p;
 	int probedirq = PARPORT_IRQ_NONE;
@@ -770,8 +773,9 @@
 		return 0;
 	}
 	((struct parport_pc_private *) (p->private_data))->ctr = 0xc;
+	p->base_hi = base_hi;
 	if (p->base != 0x3bc) {
-		if (!check_region(base+0x400,3)) {
+		if (base_hi && !check_region(base_hi,3)) {
 			p->modes |= parport_ECR_present(p);	
 			p->modes |= parport_ECP_supported(p);
 			p->modes |= parport_ECPPS2_supported(p);
@@ -791,6 +795,8 @@
 	p->size = (p->modes & (PARPORT_MODE_PCEPP 
 			       | PARPORT_MODE_PCECPEPP))?8:3;
 	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+	if (p->base_hi && (p->modes & PARPORT_MODE_PCECR))
+		printk (" (0x%lx)", p->base_hi);
 	if (p->irq == PARPORT_IRQ_AUTO) {
 		p->irq = PARPORT_IRQ_NONE;
 		parport_irq_probe(p);
@@ -829,11 +835,14 @@
 	/* Done probing.  Now put the port into a sensible start-up state. */
 	if (p->modes & PARPORT_MODE_PCECR)
 		/*
-		 * Put the ECP detected port in the more SPP like mode.
+		 * Put the ECP detected port in PS2 mode.
 		 */
-		parport_pc_write_econtrol(p, 0x0);
-	parport_pc_write_control(p, 0xc);
+		parport_pc_write_econtrol(p, 0x24);
 	parport_pc_write_data(p, 0);
+	parport_pc_write_control(p, 0x8);
+	udelay (50);
+	parport_pc_write_control(p, 0xc);
+	udelay (50);
 
 	if (parport_probe_hook)
 		(*parport_probe_hook)(p);
@@ -841,20 +850,22 @@
 	return 1;
 }
 
-int parport_pc_init(int *io, int *irq, int *dma)
+int __init parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
 {
 	int count = 0, i = 0;
 	if (io && *io) {
 		/* Only probe the ports we were given. */
 		user_specified = 1;
 		do {
-			count += probe_one_port(*(io++), *(irq++), *(dma++));
+			if (!*io_hi) *io_hi = 0x400 + *io;
+			count += probe_one_port(*(io++), *(io_hi++),
+						*(irq++), *(dma++));
 		} while (*io && (++i < PARPORT_PC_MAX_PORTS));
 	} else {
 		/* Probe all the likely ports. */
-		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]);
+		count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
+		count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
+		count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
 	}
 
 	return count;
@@ -862,10 +873,12 @@
 
 #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] = 0 };
 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 const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
 MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(io_hi, "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");
 
@@ -877,7 +890,7 @@
 	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);
+	return (parport_pc_init(io, io_hi, irqval, dma)?0:1);
 }
 
 void cleanup_module(void)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)