[PARPORT] 2.1.76 parport patches


Philip Blundell (philip@vger.rutgers.edu)
Sat, 27 Dec 1997 07:48:20 -0500 (EST)


Hi.

Here are the current parport patches against 2.1.76. Please check them
out; if there are no problems I'll try to get them merged into Linus'
tree.

p.

diff -u /vger/u4/philip/linus/linux/drivers/misc/Makefile /vger/u4/philip/linux/drivers/misc/Makefile
--- /vger/u4/philip/linus/linux/drivers/misc/Makefile Sat Nov 29 19:19:40 1997
+++ /vger/u4/philip/linux/drivers/misc/Makefile Mon Dec 22 05:35:37 1997
@@ -48,10 +48,10 @@
     M_OBJS += parport.o
   endif
   ifeq ($(CONFIG_PARPORT_PC),m)
- MX_OBJS += parport_pc.o
+ M_OBJS += parport_pc.o
   endif
   ifeq ($(CONFIG_PARPORT_AX),m)
- MX_OBJS += parport_ax.o
+ M_OBJS += parport_ax.o
   endif
 endif
 
diff -u /vger/u4/philip/linus/linux/drivers/misc/parport_ax.c /vger/u4/philip/linux/drivers/misc/parport_ax.c
--- /vger/u4/philip/linus/linux/drivers/misc/parport_ax.c Sat Dec 6 14:58:23 1997
+++ /vger/u4/philip/linux/drivers/misc/parport_ax.c Mon Dec 22 05:35:38 1997
@@ -1,4 +1,4 @@
-/* $Id: parport_ax.c,v 1.2 1997/10/25 17:27:03 philip Exp $
+/* $Id: parport_ax.c,v 1.4 1997/12/22 01:49:27 ecd Exp $
  * Parallel-port routines for Sun Ultra/AX architecture
  *
  * Author: Eddie C. Dost <ecd@skynet.be>
@@ -18,6 +18,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 
 #include <linux/parport.h>
 
@@ -515,8 +516,13 @@
         return 1;
 }
 
-int
-parport_ax_init(void)
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int parport_ax_init(void))
+#endif
 {
         struct linux_ebus *ebus;
         struct linux_ebus_device *edev;
@@ -525,17 +531,10 @@
         for_all_ebusdev(edev, ebus)
                 if (!strcmp(edev->prom_name, "ecpp"))
                         count += init_one_port(edev);
- return count;
+ return count ? 0 : -ENODEV;
 }
 
 #ifdef MODULE
-
-int
-init_module(void)
-{
- return (parport_ax_init() ? 0 : 1);
-}
-
 void
 cleanup_module(void)
 {
diff -u /vger/u4/philip/linus/linux/drivers/misc/parport_ieee1284.c /vger/u4/philip/linux/drivers/misc/parport_ieee1284.c
--- /vger/u4/philip/linus/linux/drivers/misc/parport_ieee1284.c Mon Dec 1 14:06:01 1997
+++ /vger/u4/philip/linux/drivers/misc/parport_ieee1284.c Wed Dec 3 04:22:39 1997
@@ -1,4 +1,4 @@
-/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $
+/* $Id: parport_ieee1284.c,v 1.5 1997/12/01 03:36:51 davem Exp $
  * IEEE-1284 implementation for parport.
  *
  * Authors: Phil Blundell <Philip.Blundell@pobox.com>
diff -u /vger/u4/philip/linus/linux/drivers/misc/parport_init.c /vger/u4/philip/linux/drivers/misc/parport_init.c
--- /vger/u4/philip/linus/linux/drivers/misc/parport_init.c Sat Nov 29 19:19:41 1997
+++ /vger/u4/philip/linux/drivers/misc/parport_init.c Mon Dec 22 16:51:47 1997
@@ -68,8 +68,6 @@
 #else
 __initfunc(int parport_init(void))
 {
- struct parport *pb;
-
         if (io[0] == PARPORT_DISABLE)
                 return 1;
 
diff -u /vger/u4/philip/linus/linux/drivers/misc/parport_pc.c /vger/u4/philip/linux/drivers/misc/parport_pc.c
--- /vger/u4/philip/linus/linux/drivers/misc/parport_pc.c Sat Dec 6 14:58:23 1997
+++ /vger/u4/philip/linux/drivers/misc/parport_pc.c Mon Dec 22 17:02:26 1997
@@ -1,4 +1,4 @@
-/* Parallel-port routines for PC architecture
+/* Low-level parallel-port routines for PC-style hardware.
  *
  * Authors: Phil Blundell <Philip.Blundell@pobox.com>
  * Tim Waugh <tim@cyberelk.demon.co.uk>
@@ -8,6 +8,28 @@
  * based on work by Grant Guenther <grant@torque.net> and Phil Blundell.
  */
 
+/* This driver should work with any hardware that is broadly compatible
+ * with that in the IBM PC. This applies to the majority of integrated
+ * I/O chipsets that are commonly available. The expected register
+ * layout is:
+ *
+ * base+0 data
+ * base+1 status
+ * base+2 control
+ *
+ * In addition, there are some optional registers:
+ *
+ * base+3 EPP command
+ * base+4 EPP
+ * base+0x400 ECP config A
+ * base+0x401 ECP config B
+ * base+0x402 ECP control
+ *
+ * All registers are 8 bits wide and read/write. If your hardware differs
+ * only in register addresses (eg because your registers are on 32-bit
+ * word boundaries) then you can alter the constants below to accomodate this.
+ */
+
 #include <linux/stddef.h>
 #include <linux/tasks.h>
 
@@ -26,6 +48,8 @@
 
 #include <linux/parport.h>
 
+/* --- register definitions ------------------------------- */
+
 #define ECONTROL 0x402
 #define CONFIGB 0x401
 #define CONFIGA 0x400
@@ -34,225 +58,223 @@
 #define STATUS 0x1
 #define DATA 0
 
-#define PC_MAX_PORTS 8
+/* Maximum number of ports to support. It is useless to set this greater
+ than PARPORT_MAX (in <linux/parport.h>). */
+#define PARPORT_PC_MAX_PORTS 8
 
-static void pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+static void parport_pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
         /* NULL function - Does nothing */
         return;
 }
 
-#if 0
-static void pc_write_epp(struct parport *p, unsigned int d)
+void parport_pc_write_epp(struct parport *p, unsigned int d)
 {
         outb(d, p->base+EPPREG);
 }
-#endif
 
-static unsigned int pc_read_epp(struct parport *p)
+unsigned int parport_pc_read_epp(struct parport *p)
 {
         return (unsigned int)inb(p->base+EPPREG);
 }
 
-static unsigned int pc_read_configb(struct parport *p)
+unsigned int parport_pc_read_configb(struct parport *p)
 {
         return (unsigned int)inb(p->base+CONFIGB);
 }
 
-static void pc_write_data(struct parport *p, unsigned int d)
+void parport_pc_write_data(struct parport *p, unsigned int d)
 {
         outb(d, p->base+DATA);
 }
 
-static unsigned int pc_read_data(struct parport *p)
+unsigned int parport_pc_read_data(struct parport *p)
 {
         return (unsigned int)inb(p->base+DATA);
 }
 
-static void pc_write_control(struct parport *p, unsigned int d)
+void parport_pc_write_control(struct parport *p, unsigned int d)
 {
         outb(d, p->base+CONTROL);
 }
 
-static unsigned int pc_read_control(struct parport *p)
+unsigned int parport_pc_read_control(struct parport *p)
 {
         return (unsigned int)inb(p->base+CONTROL);
 }
 
-static unsigned int pc_frob_control(struct parport *p, unsigned int mask, unsigned int val)
+unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask, unsigned int val)
 {
         unsigned int old = (unsigned int)inb(p->base+CONTROL);
         outb(((old & ~mask) ^ val), p->base+CONTROL);
         return old;
 }
 
-static void pc_write_status(struct parport *p, unsigned int d)
+void parport_pc_write_status(struct parport *p, unsigned int d)
 {
         outb(d, p->base+STATUS);
 }
 
-static unsigned int pc_read_status(struct parport *p)
+unsigned int parport_pc_read_status(struct parport *p)
 {
         return (unsigned int)inb(p->base+STATUS);
 }
 
-static void pc_write_econtrol(struct parport *p, unsigned int d)
+void parport_pc_write_econtrol(struct parport *p, unsigned int d)
 {
         outb(d, p->base+ECONTROL);
 }
 
-static unsigned int pc_read_econtrol(struct parport *p)
+unsigned int parport_pc_read_econtrol(struct parport *p)
 {
         return (unsigned int)inb(p->base+ECONTROL);
 }
 
-static unsigned int pc_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val)
+unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val)
 {
         unsigned int old = (unsigned int)inb(p->base+ECONTROL);
         outb(((old & ~mask) ^ val), p->base+ECONTROL);
         return old;
 }
 
-static void pc_change_mode(struct parport *p, int m)
+void parport_pc_change_mode(struct parport *p, int m)
 {
         /* FIXME */
 }
 
-static void pc_write_fifo(struct parport *p, unsigned int v)
+void parport_pc_write_fifo(struct parport *p, unsigned int v)
 {
         /* FIXME */
 }
 
-static unsigned int pc_read_fifo(struct parport *p)
+unsigned int parport_pc_read_fifo(struct parport *p)
 {
         return 0; /* FIXME */
 }
 
-static void pc_disable_irq(struct parport *p)
+void parport_pc_disable_irq(struct parport *p)
 {
- /* FIXME */
+ parport_pc_frob_control(p, 0x10, 0);
 }
 
-static void pc_enable_irq(struct parport *p)
+void parport_pc_enable_irq(struct parport *p)
 {
- /* FIXME */
+ parport_pc_frob_control(p, 0x10, 0x10);
 }
 
-static void pc_release_resources(struct parport *p)
+void parport_pc_release_resources(struct parport *p)
 {
         if (p->irq != PARPORT_IRQ_NONE)
- free_irq(p->irq, NULL);
+ free_irq(p->irq, p);
         release_region(p->base, p->size);
         if (p->modes & PARPORT_MODE_PCECR)
                 release_region(p->base+0x400, 3);
 }
 
-static int pc_claim_resources(struct parport *p)
+int parport_pc_claim_resources(struct parport *p)
 {
         /* FIXME check that resources are free */
         if (p->irq != PARPORT_IRQ_NONE)
- request_irq(p->irq, pc_null_intr_func, 0, p->name, NULL);
+ request_irq(p->irq, parport_pc_null_intr_func, 0, p->name, p);
         request_region(p->base, p->size, p->name);
         if (p->modes & PARPORT_MODE_PCECR)
                 request_region(p->base+0x400, 3, p->name);
         return 0;
 }
 
-static void pc_save_state(struct parport *p, struct parport_state *s)
+void parport_pc_save_state(struct parport *p, struct parport_state *s)
 {
- s->u.pc.ctr = pc_read_control(p);
- s->u.pc.ecr = pc_read_econtrol(p);
+ s->u.pc.ctr = parport_pc_read_control(p);
+ s->u.pc.ecr = parport_pc_read_econtrol(p);
 }
 
-static void pc_restore_state(struct parport *p, struct parport_state *s)
+void parport_pc_restore_state(struct parport *p, struct parport_state *s)
 {
- pc_write_control(p, s->u.pc.ctr);
- pc_write_econtrol(p, s->u.pc.ecr);
+ parport_pc_write_control(p, s->u.pc.ctr);
+ parport_pc_write_econtrol(p, s->u.pc.ecr);
 }
 
-static unsigned int pc_epp_read_block(struct parport *p, void *buf, unsigned int length)
+unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned int length)
 {
         return 0; /* FIXME */
 }
 
-static unsigned int pc_epp_write_block(struct parport *p, void *buf, unsigned int length)
+unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned int length)
 {
         return 0; /* FIXME */
 }
 
-static unsigned int pc_ecp_read_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
+unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
 {
         return 0; /* FIXME */
 }
 
-static unsigned int pc_ecp_write_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
+unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
 {
         return 0; /* FIXME */
 }
 
-static int pc_examine_irq(struct parport *p)
+int parport_pc_examine_irq(struct parport *p)
 {
         return 0; /* FIXME */
 }
 
-static void pc_inc_use_count(void)
+void parport_pc_inc_use_count(void)
 {
 #ifdef MODULE
         MOD_INC_USE_COUNT;
 #endif
 }
 
-static void pc_dec_use_count(void)
+void parport_pc_dec_use_count(void)
 {
 #ifdef MODULE
         MOD_DEC_USE_COUNT;
 #endif
 }
 
-static struct parport_operations pc_ops =
+struct parport_operations parport_pc_ops =
 {
- pc_write_data,
- pc_read_data,
+ parport_pc_write_data,
+ parport_pc_read_data,
 
- pc_write_control,
- pc_read_control,
- pc_frob_control,
+ parport_pc_write_control,
+ parport_pc_read_control,
+ parport_pc_frob_control,
 
- pc_write_econtrol,
- pc_read_econtrol,
- pc_frob_econtrol,
+ parport_pc_write_econtrol,
+ parport_pc_read_econtrol,
+ parport_pc_frob_econtrol,
 
- pc_write_status,
- pc_read_status,
+ parport_pc_write_status,
+ parport_pc_read_status,
 
- pc_write_fifo,
- pc_read_fifo,
+ parport_pc_write_fifo,
+ parport_pc_read_fifo,
         
- pc_change_mode,
+ parport_pc_change_mode,
         
- pc_release_resources,
- pc_claim_resources,
+ parport_pc_release_resources,
+ parport_pc_claim_resources,
         
- pc_epp_write_block,
- pc_epp_read_block,
+ parport_pc_epp_write_block,
+ parport_pc_epp_read_block,
 
- pc_ecp_write_block,
- pc_ecp_read_block,
+ parport_pc_ecp_write_block,
+ parport_pc_ecp_read_block,
         
- pc_save_state,
- pc_restore_state,
+ parport_pc_save_state,
+ parport_pc_restore_state,
 
- pc_enable_irq,
- pc_disable_irq,
- pc_examine_irq,
+ parport_pc_enable_irq,
+ parport_pc_disable_irq,
+ parport_pc_examine_irq,
 
- pc_inc_use_count,
- pc_dec_use_count
+ parport_pc_inc_use_count,
+ parport_pc_dec_use_count
 };
 
-/******************************************************
- * DMA detection section:
- */
+/* --- DMA detection -------------------------------------- */
 
 /*
  * Prepare DMA channels from 0-8 to transmit towards buffer
@@ -289,10 +311,10 @@
         
         for (i = 0; i < 8; i++)
                 if (dma & (1 << i)) {
- cli();
- enable_dma(i);
- sti();
- }
+ cli();
+ enable_dma(i);
+ sti();
+ }
 
         return dma;
 }
@@ -325,13 +347,13 @@
 /* Only if supports ECP mode */
 static int programmable_dma_support(struct parport *pb)
 {
- int dma, oldstate = pc_read_econtrol(pb);
+ int dma, oldstate = parport_pc_read_econtrol(pb);
 
- pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
+ parport_pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
         
- dma = pc_read_configb(pb) & 0x07;
+ dma = parport_pc_read_configb(pb) & 0x07;
 
- pc_write_econtrol(pb, oldstate);
+ parport_pc_write_econtrol(pb, oldstate);
         
         if (dma == 0 || dma == 4) /* Jumper selection */
                 return PARPORT_DMA_NONE;
@@ -405,9 +427,7 @@
         return retv;
 }
 
-/******************************************************
- * MODE detection section:
- */
+/* --- Mode detection ------------------------------------- */
 
 /*
  * Clear TIMEOUT BIT in EPP MODE
@@ -416,15 +436,15 @@
 {
         int r;
 
- if (!(pc_read_status(pb) & 0x01))
+ if (!(parport_pc_read_status(pb) & 0x01))
                 return 1;
 
         /* To clear timeout some chips require double read */
- pc_read_status(pb);
- r = pc_read_status(pb);
- pc_write_status(pb, r | 0x01); /* Some reset by writing 1 */
- pc_write_status(pb, r & 0xfe); /* Others by writing 0 */
- r = pc_read_status(pb);
+ parport_pc_read_status(pb);
+ r = parport_pc_read_status(pb);
+ parport_pc_write_status(pb, r | 0x01); /* Some reset by writing 1 */
+ parport_pc_write_status(pb, r & 0xfe); /* Others by writing 0 */
+ r = parport_pc_read_status(pb);
 
         return !(r & 0x01);
 }
@@ -436,12 +456,12 @@
 static int parport_SPP_supported(struct parport *pb)
 {
         /* Do a simple read-write test to make sure the port exists. */
- pc_write_control(pb, 0xc);
- pc_write_data(pb, 0xaa);
- if (pc_read_data(pb) != 0xaa) return 0;
+ parport_pc_write_control(pb, 0xc);
+ parport_pc_write_data(pb, 0xaa);
+ if (parport_pc_read_data(pb) != 0xaa) return 0;
         
- pc_write_data(pb, 0x55);
- if (pc_read_data(pb) != 0x55) return 0;
+ parport_pc_write_data(pb, 0x55);
+ if (parport_pc_read_data(pb) != 0x55) return 0;
 
         return PARPORT_MODE_PCSPP;
 }
@@ -460,36 +480,36 @@
  */
 static int parport_ECR_present(struct parport *pb)
 {
- unsigned int r, octr = pc_read_control(pb),
- oecr = pc_read_econtrol(pb);
+ unsigned int r, octr = parport_pc_read_control(pb),
+ oecr = parport_pc_read_econtrol(pb);
 
- r = pc_read_control(pb);
- if ((pc_read_econtrol(pb) & 0x3) == (r & 0x3)) {
- pc_write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
-
- r = pc_read_control(pb);
- if ((pc_read_econtrol(pb) & 0x2) == (r & 0x2)) {
- pc_write_control(pb, octr);
+ r = parport_pc_read_control(pb);
+ if ((parport_pc_read_econtrol(pb) & 0x3) == (r & 0x3)) {
+ parport_pc_write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
+
+ r = parport_pc_read_control(pb);
+ if ((parport_pc_read_econtrol(pb) & 0x2) == (r & 0x2)) {
+ parport_pc_write_control(pb, octr);
                         return 0; /* Sure that no ECR register exists */
                 }
         }
         
- if ((pc_read_econtrol(pb) & 0x3 ) != 0x1)
+ if ((parport_pc_read_econtrol(pb) & 0x3 ) != 0x1)
                 return 0;
 
- pc_write_econtrol(pb, 0x34);
- if (pc_read_econtrol(pb) != 0x35)
+ parport_pc_write_econtrol(pb, 0x34);
+ if (parport_pc_read_econtrol(pb) != 0x35)
                 return 0;
 
- pc_write_econtrol(pb, oecr);
- pc_write_control(pb, octr);
+ parport_pc_write_econtrol(pb, oecr);
+ parport_pc_write_control(pb, octr);
         
         return PARPORT_MODE_PCECR;
 }
 
 static int parport_ECP_supported(struct parport *pb)
 {
- int i, oecr = pc_read_econtrol(pb);
+ int i, oecr = parport_pc_read_econtrol(pb);
         
         /* If there is no ECR, we have no hope of supporting ECP. */
         if (!(pb->modes & PARPORT_MODE_PCECR))
@@ -500,11 +520,11 @@
          * it doesn't support ECP or FIFO MODE
          */
         
- pc_write_econtrol(pb, 0xc0); /* TEST FIFO */
- for (i=0; i < 1024 && (pc_read_econtrol(pb) & 0x01); i++)
- pc_write_fifo(pb, 0xaa);
+ parport_pc_write_econtrol(pb, 0xc0); /* TEST FIFO */
+ for (i=0; i < 1024 && (parport_pc_read_econtrol(pb) & 0x01); i++)
+ parport_pc_write_fifo(pb, 0xaa);
 
- pc_write_econtrol(pb, oecr);
+ parport_pc_write_econtrol(pb, oecr);
         return (i==1024)?0:PARPORT_MODE_PCECP;
 }
 
@@ -526,14 +546,14 @@
         if (!epp_clear_timeout(pb))
                 return 0; /* No way to clear timeout */
 
- pc_write_control(pb, pc_read_control(pb) | 0x20);
- pc_write_control(pb, pc_read_control(pb) | 0x10);
+ parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20);
+ parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10);
         epp_clear_timeout(pb);
         
- pc_read_epp(pb);
+ parport_pc_read_epp(pb);
         udelay(30); /* Wait for possible EPP timeout */
         
- if (pc_read_status(pb) & 0x01) {
+ if (parport_pc_read_status(pb) & 0x01) {
                 epp_clear_timeout(pb);
                 return PARPORT_MODE_PCEPP;
         }
@@ -543,17 +563,17 @@
 
 static int parport_ECPEPP_supported(struct parport *pb)
 {
- int mode, oecr = pc_read_econtrol(pb);
+ int mode, oecr = parport_pc_read_econtrol(pb);
 
         if (!(pb->modes & PARPORT_MODE_PCECR))
                 return 0;
         
         /* Search for SMC style EPP+ECP mode */
- pc_write_econtrol(pb, 0x80);
+ parport_pc_write_econtrol(pb, 0x80);
         
         mode = parport_EPP_supported(pb);
 
- pc_write_econtrol(pb, oecr);
+ parport_pc_write_econtrol(pb, oecr);
         
         return mode?PARPORT_MODE_PCECPEPP:0;
 }
@@ -577,42 +597,41 @@
 
 static int parport_PS2_supported(struct parport *pb)
 {
- int ok = 0, octr = pc_read_control(pb);
+ int ok = 0, octr = parport_pc_read_control(pb);
   
         epp_clear_timeout(pb);
 
- pc_write_control(pb, octr | 0x20); /* try to tri-state the buffer */
+ parport_pc_write_control(pb, octr | 0x20); /* try to tri-state the buffer */
         
- pc_write_data(pb, 0x55);
- if (pc_read_data(pb) != 0x55) ok++;
+ parport_pc_write_data(pb, 0x55);
+ if (parport_pc_read_data(pb) != 0x55) ok++;
 
- pc_write_data(pb, 0xaa);
- if (pc_read_data(pb) != 0xaa) ok++;
+ parport_pc_write_data(pb, 0xaa);
+ if (parport_pc_read_data(pb) != 0xaa) ok++;
         
- pc_write_control(pb, octr); /* cancel input mode */
+ parport_pc_write_control(pb, octr); /* cancel input mode */
 
         return ok?PARPORT_MODE_PCPS2:0;
 }
 
 static int parport_ECPPS2_supported(struct parport *pb)
 {
- int mode, oecr = pc_read_econtrol(pb);
+ int mode, oecr = parport_pc_read_econtrol(pb);
 
         if (!(pb->modes & PARPORT_MODE_PCECR))
                 return 0;
         
- pc_write_econtrol(pb, 0x20);
+ parport_pc_write_econtrol(pb, 0x20);
         
         mode = parport_PS2_supported(pb);
 
- pc_write_econtrol(pb, oecr);
+ parport_pc_write_econtrol(pb, oecr);
         return mode?PARPORT_MODE_PCECPPS2:0;
 }
 
-/******************************************************
- * IRQ detection section:
- *
- * This code is for detecting ECP interrupts (due to problems with the
+/* --- IRQ detection -------------------------------------- */
+
+/* This code is for detecting ECP interrupts (due to problems with the
  * monolithic interrupt probing routines).
  *
  * In short this is a voting system where the interrupt with the most
@@ -667,11 +686,11 @@
 /* Only if supports ECP mode */
 static int programmable_irq_support(struct parport *pb)
 {
- int irq, oecr = pc_read_econtrol(pb);
+ int irq, oecr = parport_pc_read_econtrol(pb);
 
- pc_write_econtrol(pb,0xE0); /* Configuration MODE */
+ parport_pc_write_econtrol(pb,0xE0); /* Configuration MODE */
         
- irq = (pc_read_configb(pb) >> 3) & 0x07;
+ irq = (parport_pc_read_configb(pb) >> 3) & 0x07;
 
         switch(irq){
         case 2:
@@ -687,26 +706,26 @@
                 irq += 7;
         }
         
- pc_write_econtrol(pb, oecr);
+ parport_pc_write_econtrol(pb, oecr);
         return irq;
 }
 
 static int irq_probe_ECP(struct parport *pb)
 {
- int irqs, i, oecr = pc_read_econtrol(pb);
+ int irqs, i, oecr = parport_pc_read_econtrol(pb);
                 
         probe_irq_off(probe_irq_on()); /* Clear any interrupts */
         irqs = open_intr_election();
                 
- pc_write_econtrol(pb, 0x00); /* Reset FIFO */
- pc_write_econtrol(pb, 0xd0); /* TEST FIFO + nErrIntrEn */
+ parport_pc_write_econtrol(pb, 0x00); /* Reset FIFO */
+ parport_pc_write_econtrol(pb, 0xd0); /* TEST FIFO + nErrIntrEn */
 
         /* If Full FIFO sure that WriteIntrThresold is generated */
- for (i=0; i < 1024 && !(pc_read_econtrol(pb) & 0x02) ; i++)
- pc_write_fifo(pb, 0xaa);
+ for (i=0; i < 1024 && !(parport_pc_read_econtrol(pb) & 0x02) ; i++)
+ parport_pc_write_fifo(pb, 0xaa);
                 
         pb->irq = close_intr_election(irqs);
- pc_write_econtrol(pb, oecr);
+ parport_pc_write_econtrol(pb, oecr);
         return pb->irq;
 }
 
@@ -716,7 +735,7 @@
  */
 static int irq_probe_EPP(struct parport *pb)
 {
- int irqs, octr = pc_read_control(pb);
+ int irqs, octr = parport_pc_read_control(pb);
 
 #ifndef ADVANCED_DETECT
         return PARPORT_IRQ_NONE;
@@ -726,27 +745,27 @@
         irqs = open_intr_election();
 
         if (pb->modes & PARPORT_MODE_PCECR)
- pc_write_econtrol(pb, pc_read_econtrol(pb) | 0x10);
+ parport_pc_write_econtrol(pb, parport_pc_read_econtrol(pb) | 0x10);
         
         epp_clear_timeout(pb);
- pc_write_control(pb, pc_read_control(pb) | 0x20);
- pc_write_control(pb, pc_read_control(pb) | 0x10);
+ parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20);
+ parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10);
         epp_clear_timeout(pb);
 
         /* Device isn't expecting an EPP read
          * and generates an IRQ.
          */
- pc_read_epp(pb);
+ parport_pc_read_epp(pb);
         udelay(20);
 
         pb->irq = close_intr_election(irqs);
- pc_write_control(pb, octr);
+ parport_pc_write_control(pb, octr);
         return pb->irq;
 }
 
 static int irq_probe_SPP(struct parport *pb)
 {
- int irqs, octr = pc_read_control(pb);
+ int irqs, octr = parport_pc_read_control(pb);
 
 #ifndef ADVANCED_DETECT
         return PARPORT_IRQ_NONE;
@@ -756,26 +775,26 @@
         irqs = probe_irq_on();
 
         if (pb->modes & PARPORT_MODE_PCECR)
- pc_write_econtrol(pb, 0x10);
+ parport_pc_write_econtrol(pb, 0x10);
 
- pc_write_data(pb,0x00);
- pc_write_control(pb,0x00);
- pc_write_control(pb,0x0c);
+ parport_pc_write_data(pb,0x00);
+ parport_pc_write_control(pb,0x00);
+ parport_pc_write_control(pb,0x0c);
         udelay(5);
- pc_write_control(pb,0x0d);
+ parport_pc_write_control(pb,0x0d);
         udelay(5);
- pc_write_control(pb,0x0c);
+ parport_pc_write_control(pb,0x0c);
         udelay(25);
- pc_write_control(pb,0x08);
+ parport_pc_write_control(pb,0x08);
         udelay(25);
- pc_write_control(pb,0x0c);
+ parport_pc_write_control(pb,0x0c);
         udelay(50);
 
         pb->irq = probe_irq_off(irqs);
         if (pb->irq <= 0)
                 pb->irq = PARPORT_IRQ_NONE; /* No interrupt detected */
         
- pc_write_control(pb, octr);
+ parport_pc_write_control(pb, octr);
         return pb->irq;
 }
 
@@ -796,10 +815,10 @@
                         
         if (pb->irq == PARPORT_IRQ_NONE &&
             (pb->modes & PARPORT_MODE_PCECPEPP)) {
- int oecr = pc_read_econtrol(pb);
- pc_write_econtrol(pb, 0x80);
+ int oecr = parport_pc_read_econtrol(pb);
+ parport_pc_write_econtrol(pb, 0x80);
                 pb->irq = irq_probe_EPP(pb);
- pc_write_econtrol(pb, oecr);
+ parport_pc_write_econtrol(pb, oecr);
         }
 
         epp_clear_timeout(pb);
@@ -815,14 +834,16 @@
         return pb->irq;
 }
 
+/* --- Initialisation code -------------------------------- */
+
 static int probe_one_port(unsigned long int base, int irq, int dma)
 {
         struct parport tmpport, *p;
         if (check_region(base, 3)) return 0;
         tmpport.base = base;
- tmpport.ops = &pc_ops;
+ tmpport.ops = &parport_pc_ops;
         if (!(parport_SPP_supported(&tmpport))) return 0;
- if (!(p = parport_register_port(base, irq, dma, &pc_ops))) return 0;
+ if (!(p = parport_register_port(base, irq, dma, &parport_pc_ops))) return 0;
         p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p);
         if (p->base != 0x3bc) {
                 if (!check_region(base+0x400,3)) {
@@ -866,8 +887,8 @@
         p->flags |= PARPORT_FLAG_COMA;
 
         /* Done probing. Now put the port into a sensible start-up state. */
- pc_write_control(p, 0xc);
- pc_write_data(p, 0);
+ parport_pc_write_control(p, 0xc);
+ parport_pc_write_data(p, 0);
 
         if (parport_probe_hook)
                 (*parport_probe_hook)(p);
@@ -882,7 +903,7 @@
                 /* Only probe the ports we were given. */
                 do {
                         count += probe_one_port(*(io++), *(irq++), *(dma++));
- } while (*io && (++i < PC_MAX_PORTS));
+ } while (*io && (++i < PARPORT_PC_MAX_PORTS));
         } else {
                 /* Probe all the likely ports. */
                 count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
@@ -893,12 +914,12 @@
 }
 
 #ifdef MODULE
-static int io[PC_MAX_PORTS+1] = { [0 ... PC_MAX_PORTS] = 0 };
-static int dma[PC_MAX_PORTS] = { [0 ... PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
-static int irq[PC_MAX_PORTS] = { [0 ... PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
-MODULE_PARM(io, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
-MODULE_PARM(dma, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
+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 };
+MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
 
 int init_module(void)
 {
diff -u /vger/u4/philip/linus/linux/drivers/misc/parport_share.c /vger/u4/philip/linux/drivers/misc/parport_share.c
--- /vger/u4/philip/linus/linux/drivers/misc/parport_share.c Mon Dec 1 17:49:02 1997
+++ /vger/u4/philip/linux/drivers/misc/parport_share.c Mon Dec 22 17:03:36 1997
@@ -1,4 +1,4 @@
-/* $Id: parport_share.c,v 1.8 1997/11/08 18:55:29 philip Exp $
+/* $Id: parport_share.c,v 1.10 1997/12/22 22:03:36 philip Exp $
  * Parallel-port resource manager code.
  *
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
@@ -279,10 +279,16 @@
 
         /* Swap the IRQ handlers. */
         if (dev->port->irq != PARPORT_IRQ_NONE) {
- free_irq(dev->port->irq, pd1?pd1->private:NULL);
- request_irq(dev->port->irq, dev->irq_func ? dev->irq_func :
- parport_null_intr_func, SA_INTERRUPT, dev->name,
- dev->private);
+ if (pd1 && pd1->irq_func) {
+ free_irq(dev->port->irq,pd1->private);
+ request_irq(dev->port->irq, parport_null_intr_func,
+ SA_INTERRUPT, dev->port->name, NULL);
+ }
+ if (dev->irq_func) {
+ free_irq(dev->port->irq, NULL);
+ request_irq(dev->port->irq, dev->irq_func,
+ SA_INTERRUPT, dev->name, dev->private);
+ }
         }
 
         /* Restore control registers */
@@ -306,7 +312,7 @@
         dev->port->ops->save_state(dev->port, dev->state);
 
         /* Point IRQs somewhere harmless. */
- if (dev->port->irq != PARPORT_IRQ_NONE) {
+ if (dev->port->irq != PARPORT_IRQ_NONE && dev->irq_func) {
                 free_irq(dev->port->irq, dev->private);
                 request_irq(dev->port->irq, parport_null_intr_func,
                             SA_INTERRUPT, dev->port->name, NULL);
--- /vger/u4/philip/linus/linux/drivers/char/lp.c Sun Nov 30 17:00:38 1997
+++ /vger/u4/philip/linux/drivers/char/lp.c Mon Dec 22 16:56:52 1997
@@ -1,4 +1,6 @@
 /*
+ * Generic parallel printer driver
+ *
  * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
  * Copyright (C) 1992,1993 by Michael K. Johnson
  * - Thanks much to Gunter Windau for pointing out to me where the error
@@ -11,12 +13,55 @@
  * lp_read (Status readback) support added by Carsten Gross,
  * carsten@sol.wohnheim.uni-ulm.de
  * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
- * Reverted interrupt to polling at runtime if more than one device is parport
- * registered and joined the interrupt and polling code.
- * by Andrea Arcangeli <arcangeli@mbox.queen.it>
+ * parport_sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
  */
 
-/* This driver is about due for a rewrite. */
+/* This driver should, in theory, work with any parallel port that has an
+ * appropriate low-level driver; all I/O is done through the parport abstraction
+ * layer. There is a performance penalty for this, but parallel ports are
+ * comparitively low-speed devices anyway. It should be possible to eliminate or
+ * reduce this overhead in the common case, as well.
+ *
+ * If this driver is built into the kernel, you can configure it using the kernel
+ * command-line... For example:
+ *
+ * lp=parport1,none,parport2 (bind lp0 to parport1, disable lp1 and
+ * bind lp2 to parport2)
+ *
+ * lp=auto (assign lp devices to all ports that
+ * have printers attached, as determined
+ * by the IEEE-1284 autoprobe)
+ *
+ * lp=reset (reset the printer during initialisation)
+ *
+ * lp=off (disable the printer driver entirely)
+ *
+ * If the driver is loaded as a module, similar functionality is available using
+ * module parameters. The equivalent of the above commands would be:
+ *
+ * # insmod lp.o parport=1,-1,2 (use -1 for disabled ports, since module
+ * parameters do not allow you to mix textual
+ * and numeric values)
+ *
+ * # insmod lp.o autoprobe=1
+ *
+ * # insmod lp.0 reset=1
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Under Linux 2.0 and previous versions, lp devices were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ * lp0 0x3bc
+ * lp1 0x378
+ * lp2 0x278
+ *
+ * The new driver, by default, binds lp devices to parport devices as it
+ * finds them. This means that if you only have one port, it will be bound
+ * to lp0 regardless of its I/O address. If you need the old behaviour, you
+ * can force it using the parameters described above.
+ */
 
 #include <linux/module.h>
 
@@ -26,31 +71,24 @@
 #include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/malloc.h>
-#include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 
+#include <linux/parport.h>
+#include <linux/lp.h>
+
 #include <asm/irq.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <linux/parport.h>
-#include <linux/lp.h>
 
 /* if you have more than 3 printers, remember to increase LP_NO */
-struct lp_struct lp_table[] =
-{
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
- {0}},
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
- {0}},
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
- {0}}
-};
 #define LP_NO 3
 
-/* Device name */
-static char *dev_name = "lp";
+struct lp_struct lp_table[LP_NO] =
+{
+ [0 ... LP_NO-1] = {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT,
+ NULL, NULL, 0, 0, 0, 0, {0}}
+};
 
 /* Test if printer is ready (and optionally has no error conditions) */
 #define LP_READY(minor, status) \
@@ -64,10 +102,7 @@
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
 
-/* Magic numbers */
-#define AUTO -3
-#define OFF -2
-#define UNSPEC -1
+/* --- parport support functions ------------------------------- */
 
 static inline void lp_parport_release (int minor)
 {
@@ -81,22 +116,27 @@
                 sleep_on (&lp_table[minor].lp_wait_q);
 }
 
-static inline void lp_schedule (int minor)
+static void lp_wakeup(void *ref)
 {
- if (lp_table[minor].should_relinquish) {
- lp_parport_release (minor);
- schedule ();
- lp_parport_claim (minor);
- }
- else
- schedule ();
-}
+ struct lp_struct *lp_dev = (struct lp_struct *) ref;
 
+ if (!waitqueue_active (&lp_dev->lp_wait_q))
+ return; /* Wake up whom? */
 
-static int lp_preempt (void *handle)
+ /* Claim the Parport */
+ if (parport_claim(lp_dev->dev))
+ return; /* Shouldn't happen */
+
+ wake_up(&lp_dev->lp_wait_q);
+}
+
+static int lp_preempt(void *handle)
 {
         struct lp_struct *lps = (struct lp_struct *)handle;
 
+ if (waitqueue_active (&lps->lp_wait_q))
+ wake_up_interruptible(&lps->lp_wait_q);
+
         /* Just remember that someone wants the port */
         lps->should_relinquish = 1;
 
@@ -104,12 +144,34 @@
         return 1;
 }
 
+/* --- low-level port access ----------------------------------- */
+
+#define r_dtr(x) (parport_read_data(lp_table[(x)].dev->port))
+#define r_str(x) (parport_read_status(lp_table[(x)].dev->port))
+#define w_ctr(x,y) do { parport_write_control(lp_table[(x)].dev->port, (y)); } while (0)
+#define w_dtr(x,y) do { parport_write_data(lp_table[(x)].dev->port, (y)); } while (0)
+
+static inline void lp_schedule (int minor)
+{
+ if (lp_table[minor].should_relinquish) {
+ lp_parport_release (minor);
+ schedule ();
+ lp_parport_claim (minor);
+ }
+ else
+ schedule ();
+}
+
 static int lp_reset(int minor)
 {
+ int retval;
+ lp_parport_claim(minor);
         w_ctr(minor, LP_PSELECP);
         udelay(LP_DELAY);
         w_ctr(minor, LP_PSELECP | LP_PINITP);
- return r_str(minor);
+ retval = r_str(minor);
+ lp_parport_release(minor);
+ return retval;
 }
 
 static inline int must_use_polling(int minor)
@@ -118,7 +180,7 @@
                       lp_table[minor].dev->port->devices->next;
 }
 
-static inline int lp_char(char lpchar, int minor, int use_polling)
+static inline int lp_char(char lpchar, int minor)
 {
         int status;
         unsigned int wait = 0;
@@ -128,26 +190,32 @@
         do {
                 status = r_str(minor);
                 count++;
- if (need_resched)
+ if (need_resched || lp_table[minor].should_relinquish)
                         lp_schedule (minor);
- } while (((use_polling && !LP_READY(minor, status)) ||
- (!use_polling && !(status & LP_PBUSY))) &&
- (count < LP_CHAR(minor)));
+ } while (!LP_READY(minor, status) && count < LP_CHAR(minor));
 
- if (count == LP_CHAR(minor) ||
- (!use_polling && !LP_CAREFUL_READY(minor, status)))
+ if (count == LP_CHAR(minor))
                 return 0;
+
         w_dtr(minor, lpchar);
         stats = &LP_STAT(minor);
         stats->chars++;
         /* must wait before taking strobe high, and after taking strobe
            low, according spec. Some printers need it, others don't. */
+#ifndef __sparc__
         while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */
                 wait++;
+#else
+ udelay(1);
+#endif
         /* control port takes strobe high */
         w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
+#ifndef __sparc__
         while (wait) /* FIXME: should be a udelay() */
                 wait--;
+#else
+ udelay(1);
+#endif
         /* take strobe low */
         w_ctr(minor, LP_PSELECP | LP_PINITP);
         /* update waittime statistics */
@@ -171,18 +239,41 @@
         struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
 
         if (waitqueue_active (&lp_dev->lp_wait_q))
- wake_up(&lp_dev->lp_wait_q);
+ wake_up_interruptible(&lp_dev->lp_wait_q);
 }
 
+#define LP_POLLING(minor) lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE
+
 static void lp_error(int minor)
 {
- if (must_use_polling(minor)) {
+ if (LP_POLLING(minor) || lp_table[minor].should_relinquish) {
                 current->state = TASK_INTERRUPTIBLE;
                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
                 lp_schedule (minor);
         }
 }
 
+static int lp_check_status(int minor) {
+ unsigned char status = r_str(minor);
+ if ((status & LP_POUTPA)) {
+ printk(KERN_INFO "lp%d out of paper\n", minor);
+ if (LP_F(minor) & LP_ABORT)
+ return 1;
+ lp_error(minor);
+ } else if (!(status & LP_PSELECD)) {
+ printk(KERN_INFO "lp%d off-line\n", minor);
+ if (LP_F(minor) & LP_ABORT)
+ return 1;
+ lp_error(minor);
+ } else if (!(status & LP_PERRORP)) {
+ printk(KERN_ERR "lp%d printer error\n", minor);
+ if (LP_F(minor) & LP_ABORT)
+ return 1;
+ lp_error(minor);
+ }
+ return 0;
+}
+
 static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
 {
         unsigned long copy_size;
@@ -202,7 +293,7 @@
                 copy_from_user(lp->lp_buffer, buf, copy_size);
 
                 while (copy_size) {
- if (lp_char(lp->lp_buffer[bytes_written], minor, must_use_polling(minor))) {
+ if (lp_char(lp->lp_buffer[bytes_written], minor)) {
                                 --copy_size;
                                 ++bytes_written;
                                 lp_table[minor].runchars++;
@@ -210,36 +301,24 @@
                                 int rc = total_bytes_written + bytes_written;
                                 if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
                                         LP_STAT(minor).maxrun = lp_table[minor].runchars;
- status = r_str(minor);
- if ((status & LP_POUTPA)) {
- printk(KERN_INFO "lp%d out of paper\n", minor);
- if (LP_F(minor) & LP_ABORT)
- return rc ? rc : -ENOSPC;
- lp_error(minor);
- } else if (!(status & LP_PSELECD)) {
- printk(KERN_INFO "lp%d off-line\n", minor);
- if (LP_F(minor) & LP_ABORT)
- return rc ? rc : -EIO;
- lp_error(minor);
- } else if (!(status & LP_PERRORP)) {
- printk(KERN_ERR "lp%d printer error\n", minor);
- if (LP_F(minor) & LP_ABORT)
- return rc ? rc : -EIO;
- lp_error(minor);
- }
-
                                 LP_STAT(minor).sleeps++;
 
- if (must_use_polling(minor)) {
+ if (LP_POLLING(minor)) {
+ lp_polling:
+ if (lp_check_status(minor))
+ return rc ? rc : -EIO;
 #ifdef LP_DEBUG
                                         printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp_table[minor].runchars, LP_TIME(minor));
 #endif
- lp_table[minor].runchars = 0;
                                         current->state = TASK_INTERRUPTIBLE;
                                         current->timeout = jiffies + LP_TIME(minor);
                                         lp_schedule (minor);
                                 } else {
                                         cli();
+ if (lp_table[minor].should_relinquish) {
+ sti();
+ goto lp_polling;
+ }
                                         enable_irq(lp->dev->port->irq);
                                         w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN);
                                         status = r_str(minor);
@@ -249,14 +328,16 @@
                                                 sti();
                                                 continue;
                                         }
- lp_table[minor].runchars = 0;
                                         current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
                                         interruptible_sleep_on(&lp->lp_wait_q);
-
                                         w_ctr(minor, LP_PSELECP | LP_PINITP);
                                         sti();
+ if (lp_check_status(minor))
+ return rc ? rc : -EIO;
                                 }
 
+ lp_table[minor].runchars = 0;
+
                                 if (signal_pending(current)) {
                                         if (total_bytes_written + bytes_written)
                                                 return total_bytes_written + bytes_written;
@@ -292,7 +373,7 @@
          lp_parport_claim (minor);
 
         retv = lp_write_buf(minor, buf, count);
-
+
          lp_parport_release (minor);
          return retv;
 }
@@ -307,14 +388,15 @@
 static int lp_read_nibble(int minor)
 {
         unsigned char i;
- i=r_str(minor)>>3;
- i&=~8;
- if ( ( i & 0x10) == 0) i|=8;
- return(i & 0x0f);
+ i = r_str(minor)>>3;
+ i &= ~8;
+ if ((i & 0x10) == 0) i |= 8;
+ return (i & 0x0f);
 }
 
-static void lp_select_in_high(int minor) {
- w_ctr(minor, (r_ctr(minor) | 8));
+static inline void lp_select_in_high(int minor)
+{
+ parport_frob_control(lp_table[minor].dev->port, 8, 8);
 }
 
 /* Status readback confirming to ieee1284 */
@@ -351,26 +433,27 @@
                 return temp-buf; /* End of file */
         }
         for (i=0; i<=(count*2); i++) {
- w_ctr(minor, r_ctr(minor) | 2); /* AutoFeed high */
+ parport_frob_control(lp_table[minor].dev->port, 2, 2); /* AutoFeed high */
                 do {
- status=(r_str(minor) & 0x40);
+ status = (r_str(minor) & 0x40);
                         udelay(50);
                         counter++;
                         if (need_resched)
                                 schedule ();
- } while ( (status == 0x40) && (counter < 20) );
- if ( counter == 20 ) { /* Timeout */
+ } while ((status == 0x40) && (counter < 20));
+ if (counter == 20) {
+ /* Timeout */
 #ifdef LP_READ_DEBUG
                         printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n");
-#endif
- w_ctr(minor, r_ctr(minor) & ~2);
+#endif
+ parport_frob_control(lp_table[minor].dev->port, 2, 0);
                         lp_select_in_high(minor);
                         parport_release(lp_table[minor].dev);
                         return temp-buf; /* end the read at timeout */
                 }
                 counter=0;
- z=lp_read_nibble(minor);
- w_ctr(minor, r_ctr(minor) & ~2); /* AutoFeed low */
+ z = lp_read_nibble(minor);
+ parport_frob_control(lp_table[minor].dev->port, 2, 0); /* AutoFeed low */
                 do {
                         status=(r_str(minor) & 0x40);
                         udelay(20);
@@ -571,19 +654,27 @@
         lp_release
 };
 
-static int parport[LP_NO] = { UNSPEC, };
+/* --- initialisation code ------------------------------------- */
 
 #ifdef MODULE
-#define lp_init init_module
+
+static int parport[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int reset = 0;
+static int autoprobe = 0;
+
 MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "i");
+MODULE_PARM(reset, "i");
+MODULE_PARM(autoprobe, "i");
 
 #else
 
+static int parport[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int reset __initdata = 0;
+
 static int parport_ptr = 0;
 
-void lp_setup(char *str, int *ints)
+__initfunc(void lp_setup(char *str, int *ints))
 {
- /* Ugh. */
         if (!strncmp(str, "parport", 7)) {
                 int n = simple_strtoul(str+7, NULL, 10);
                 if (parport_ptr < LP_NO)
@@ -592,11 +683,15 @@
                         printk(KERN_INFO "lp: too many ports, %s ignored.\n",
                                str);
         } else if (!strcmp(str, "auto")) {
- parport[0] = AUTO;
+ parport[0] = LP_PARPORT_AUTO;
+ } else if (!strcmp(str, "none")) {
+ parport_ptr++;
+ } else if (!strcmp(str, "reset")) {
+ reset = 1;
         } else {
                 if (ints[0] == 0 || ints[1] == 0) {
                         /* disable driver on "lp=" or "lp=0" */
- parport[0] = OFF;
+ parport[0] = LP_PARPORT_OFF;
                 } else {
                         printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
                 }
@@ -605,87 +700,92 @@
 
 #endif
 
-void lp_wakeup(void *ref)
+int lp_register(int nr, struct parport *port)
 {
- struct lp_struct *lp_dev = (struct lp_struct *) ref;
-
- if (!waitqueue_active (&lp_dev->lp_wait_q))
- return; /* Wake up whom? */
+ lp_table[nr].dev = parport_register_device(port, "lp",
+ lp_preempt, lp_wakeup,
+ lp_interrupt,
+ PARPORT_DEV_TRAN,
+ (void *) &lp_table[nr]);
+ if (lp_table[nr].dev == NULL)
+ return 1;
+ lp_table[nr].flags |= LP_EXIST;
+ init_waitqueue (&lp_table[nr].lp_wait_q);
 
- /* Claim the Parport */
- if (parport_claim(lp_dev->dev))
- return; /* Shouldn't happen */
+ if (reset)
+ lp_reset(nr);
 
- wake_up(&lp_dev->lp_wait_q);
-}
+ printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
+ (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
 
-static int inline lp_searchfor(int list[], int a)
-{
- int i;
- for (i = 0; i < LP_NO && list[i] != UNSPEC; i++) {
- if (list[i] == a) return 1;
- }
         return 0;
 }
 
 int lp_init(void)
 {
- int count = 0;
- struct parport *pb;
-
- if (parport[0] == OFF) return 0;
-
- pb = parport_enumerate();
-
- while (pb) {
- /* We only understand PC-style ports. */
- if (pb->modes & PARPORT_MODE_PCSPP) {
- if (parport[0] == UNSPEC ||
- lp_searchfor(parport, count) ||
- (parport[0] == AUTO &&
- pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
- lp_table[count].dev =
- parport_register_device(pb, dev_name,
- lp_preempt, lp_wakeup,
- lp_interrupt, PARPORT_DEV_TRAN,
- (void *) &lp_table[count]);
- lp_table[count].flags |= LP_EXIST;
- init_waitqueue (&lp_table[count].lp_wait_q);
- lp_parport_claim (count);
- lp_reset (count);
- lp_parport_release (count);
- printk(KERN_INFO "lp%d: using %s (%s).\n",
- count, pb->name, (pb->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
+ unsigned int count = 0;
+ struct parport *port;
+
+ switch (parport[0])
+ {
+ case LP_PARPORT_OFF:
+ return 0;
+
+ case LP_PARPORT_UNSPEC:
+ case LP_PARPORT_AUTO:
+ for (port = parport_enumerate(); port; port = port->next) {
+
+ if (parport[0] == LP_PARPORT_AUTO &&
+ port->probe_info.class != PARPORT_CLASS_PRINTER)
+ continue;
+
+ if (!lp_register(count, port))
+ if (++count == LP_NO)
+ break;
+ }
+ break;
+
+ default:
+ for (count = 0; count < LP_NO; count++) {
+ if (parport[count] != LP_PARPORT_UNSPEC) {
+ char buffer[16];
+ sprintf(buffer, "parport%d", parport[count]);
+ for (port = parport_enumerate(); port;
+ port = port->next) {
+ if (!strcmp(port->name, buffer)) {
+ (void) lp_register(count, port);
+ break;
+ }
+ }
                         }
- if (++count == LP_NO)
- break;
                 }
- pb = pb->next;
- }
+ break;
+ }
 
- /* Successful specified devices increase count
- * Unsuccessful specified devices increase failed
- */
- if (count) {
+ if (count) {
                 if (register_chrdev(LP_MAJOR, "lp", &lp_fops)) {
                         printk("lp: unable to get major %d\n", LP_MAJOR);
                         return -EIO;
                 }
- return 0;
+ } else {
+ printk(KERN_INFO "lp: driver loaded but no devices found\n");
         }
 
- printk(KERN_INFO "lp: driver loaded but no devices found\n");
-#ifdef MODULE
         return 0;
-#else
- return 1;
-#endif
 }
 
 #ifdef MODULE
+int init_module(void)
+{
+ if (autoprobe)
+ parport[0] = LP_PARPORT_AUTO;
+
+ return lp_init();
+}
+
 void cleanup_module(void)
 {
- int offset;
+ unsigned int offset;
 
         unregister_chrdev(LP_MAJOR, "lp");
         for (offset = 0; offset < LP_NO; offset++) {
--- /vger/u4/philip/linus/linux/include/linux/lp.h Tue Aug 26 17:52:45 1997
+++ /vger/u4/philip/linux/include/linux/lp.h Mon Dec 22 16:53:57 1997
@@ -7,6 +7,11 @@
  * Interrupt support added 1993 Nigel Gamble
  */
 
+/* Magic numbers for defining port-device mappings */
+#define LP_PARPORT_AUTO -3
+#define LP_PARPORT_OFF -2
+#define LP_PARPORT_UNSPEC -1
+
 /*
  * Per POSIX guidelines, this module reserves the LP and lp prefixes
  * These are the lp_table[minor].flags flags...
@@ -88,20 +93,6 @@
 #define LP_BUFFER_SIZE 256
 
 #define LP_BASE(x) lp_table[(x)].dev->port->base
-
-#define r_dtr(x) inb(LP_BASE(x))
-#define r_str(x) inb(LP_BASE(x)+1)
-#define r_ctr(x) inb(LP_BASE(x)+2)
-#define r_epp(x) inb(LP_BASE(x)+4)
-#define r_fifo(x) inb(LP_BASE(x)+0x400)
-#define r_ecr(x) inb(LP_BASE(x)+0x402)
-
-#define w_dtr(x,y) outb((y), LP_BASE(x))
-#define w_str(x,y) outb((y), LP_BASE(x)+1)
-#define w_ctr(x,y) outb((y), LP_BASE(x)+2)
-#define w_epp(x,y) outb((y), LP_BASE(x)+4)
-#define w_fifo(x,y) outb((y), LP_BASE(x)+0x400)
-#define w_ecr(x,y) outb((y), LP_BASE(x)+0x402)
 
 struct lp_stats {
         unsigned long chars;

-- 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:14 EST