[PARPORT] more patches


Philip Blundell (Philip.Blundell@pobox.com)
Sun, 28 Dec 1997 22:17:53 +0000


Hi.

I hacked on parport_procfs a bit. I think that dynamic IRQ setting stands at
least a chance of working now. Please check it out. I also did the usual
round of code cleanups.

p.

Index: drivers/misc/parport_arc.c
===================================================================
RCS file: /disks/c7/repository/linux/drivers/misc/parport_arc.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 parport_arc.c
--- parport_arc.c 1997/10/06 18:04:43 1.1.1.2
+++ parport_arc.c 1997/12/25 13:51:16
@@ -1,24 +1,32 @@
-/* Parallel-port routines for ARC onboard hardware.
+/* Low-level parallel port routines for Archimedes onboard hardware
  *
  * Author: Phil Blundell <Philip.Blundell@pobox.com>
  */
 
-#include <linux/tasks.h>
-
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/dma.h>
+/* This driver is for the parallel port hardware found on Acorn's old
+ * range of Archimedes machines. The A5000 and newer systems have PC-style
+ * I/O hardware and should use the parport_pc driver instead.
+ *
+ * The Acorn printer port hardware is very simple. There is a single 8-bit
+ * write-only latch for the data port and control/status bits are handled
+ * with various auxilliary input and output lines. The port is not
+ * bidirectional, does not support any modes other than SPP, and has only
+ * a subset of the standard printer control lines connected.
+ */
 
+#include <linux/tasks.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
-
 #include <linux/parport.h>
 
-#include <linux/arch/oldlatches.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/arch/oldlatches.h>
+#include <asm/arch/irqs.h>
 
 #define DATA_LATCH 0x3350010
 
@@ -50,7 +58,7 @@
 #endif
 }
 
-static struct parport_operations arc_ops =
+static struct parport_operations parport_arc_ops =
 {
         arc_write_data,
         arc_read_data,
@@ -90,3 +98,31 @@
         arc_inc_use_count,
         arc_dec_use_count
 };
+
+/* --- Initialisation code -------------------------------- */
+
+int parport_arc_init(void)
+{
+ /* Archimedes hardware provides only one port, at a fixed address */
+ struct parport *p;
+
+ if (check_region(DATA_LATCH, 4))
+ return 0;
+
+ if (!(p = parport_register_port(base, IRQ_PRINTERACK,
+ PARPORT_DMA_NONE, &parport_arc_ops)))
+ return 0;
+
+ p->modes = PARPORT_MODE_ARCSPP;
+ p->size = 4;
+
+ printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
+ p->irq);
+ parport_proc_register(p);
+ p->flags |= PARPORT_FLAG_COMA;
+
+ if (parport_probe_hook)
+ (*parport_probe_hook)(p);
+
+ return 1;
+}
Index: drivers/misc/parport_init.c
===================================================================
RCS file: /disks/c7/repository/linux/drivers/misc/parport_init.c,v
retrieving revision 1.5
diff -u -r1.5 parport_init.c
--- parport_init.c 1997/12/24 22:37:32 1.5
+++ parport_init.c 1997/12/28 21:38:53
@@ -1,6 +1,6 @@
 /* Parallel-port initialisation code.
  *
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
+ * Authors: David Campbell <campbell@torque.net>
  * Tim Waugh <tim@cyberelk.demon.co.uk>
  * Jose Renau <renau@acm.org>
  *
@@ -57,7 +57,7 @@
 #ifdef MODULE
 int init_module(void)
 {
- parport_proc_init();
+ (void)parport_proc_init(); /* We can go on without it. */
         return 0;
 }
 
@@ -74,7 +74,7 @@
 #ifdef CONFIG_PNP_PARPORT
         parport_probe_hook = &parport_probe_one;
 #endif
- parport_proc_init();
+ (void)parport_proc_init();
 #ifdef CONFIG_PARPORT_PC
         parport_pc_init(io, irq, dma);
 #endif
Index: drivers/misc/parport_procfs.c
===================================================================
RCS file: /disks/c7/repository/linux/drivers/misc/parport_procfs.c,v
retrieving revision 1.2
diff -u -r1.2 parport_procfs.c
--- parport_procfs.c 1997/10/18 12:12:21 1.2
+++ parport_procfs.c 1997/12/28 22:07:54
@@ -1,10 +1,11 @@
 /* Parallel port /proc interface code.
  *
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
- * Tim Waugh <tmw20@cam.ac.uk>
+ * Authors: David Campbell <campbell@torque.net>
+ * Tim Waugh <tim@cyberelk.demon.co.uk>
+ * Philip Blundell <philb@gnu.org>
  *
  * based on work by Grant Guenther <grant@torque.net>
- * and Philip Blundell <Philip.Blundell@pobox.com>
+ * and Philip Blundell
  */
 
 #include <linux/stddef.h>
@@ -19,14 +20,10 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
-
 #include <linux/proc_fs.h>
-
 #include <linux/parport.h>
 
-#undef PARPORT_INCLUDE_BENCH
-
-struct proc_dir_entry *base=NULL;
+struct proc_dir_entry *base = NULL;
 
 extern void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
 
@@ -37,23 +34,27 @@
         struct parport *pp = (struct parport *)data;
         
         if (count > 4 ) /* more than 4 digits for a irq 0x?? 0?? ?? */
- return(-EOVERFLOW);
+ return -EOVERFLOW;
 
         if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) {
                 newirq = PARPORT_IRQ_NONE;
         } else {
                 if (buffer[0] == '0') {
- if( buffer[1] == 'x' )
- newirq = simple_strtoul(&buffer[2],0,16);
+ if (buffer[1] == 'x')
+ newirq = simple_strtoul(&buffer[2], 0, 16);
                         else
- newirq = simple_strtoul(&buffer[1],0,8);
+ newirq = simple_strtoul(&buffer[1], 0, 8);
                 } else {
- newirq = simple_strtoul(buffer,0,10);
+ newirq = simple_strtoul(buffer, 0, 10);
                 }
         }
 
- if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA))
- free_irq(pp->irq, pp);
+ if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) {
+ if (pp->cad->irq_func)
+ free_irq(pp->irq, pp->cad->private);
+ else
+ free_irq(pp->irq, NULL);
+ }
 
         pp->irq = newirq;
 
@@ -66,11 +67,12 @@
                                 request_irq(pp->irq, pd->irq_func ?
                                             pd->irq_func :
                                             parport_null_intr_func,
- SA_INTERRUPT, pd->name, pd->port);
+ SA_INTERRUPT, pd->name,
+ pd->private);
                 } else {
                         request_irq(pp->irq, pd->irq_func ? pd->irq_func :
                                     parport_null_intr_func,
- SA_INTERRUPT, pp->name, pd->port);
+ SA_INTERRUPT, pp->name, NULL);
                 }
         }
 
@@ -102,16 +104,16 @@
 
         for (pd1 = pp->devices; pd1 ; pd1 = pd1->next) {
                 if (pd1 == pp->cad)
- len += sprintf(page+len, "+");
+ page[len++] = '+';
                 else
- len += sprintf(page+len, " ");
+ page[len++] = ' ';
 
- len += sprintf(page+len, "%s",pd1->name);
+ len += sprintf(page+len, "%s", pd1->name);
 
                 if (pd1 == pp->lurker)
- len += sprintf(page+len, " LURK");
+ len += sprintf(page+len, " [LURK]");
                 
- len += sprintf(page+len,"\n");
+ page[len++] = '\n';
         }
                 
         *start = 0;
@@ -120,26 +122,26 @@
 }
 
 static int hardware_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
 {
         struct parport *pp = (struct parport *)data;
         int len=0;
         
         len += sprintf(page+len, "base:\t0x%lx\n",pp->base);
+
         if (pp->irq == PARPORT_IRQ_NONE)
                 len += sprintf(page+len, "irq:\tnone\n");
         else
                 len += sprintf(page+len, "irq:\t%d\n",pp->irq);
+
         if (pp->dma == PARPORT_DMA_NONE)
                 len += sprintf(page+len, "dma:\tnone\n");
         else
                 len += sprintf(page+len, "dma:\t%d\n",pp->dma);
 
-
-#if 0
         len += sprintf(page+len, "modes:\t");
         {
-#define printmode(x) {if(pp->modes&PARPORT_MODE_##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
+#define printmode(x) {if(pp->modes&PARPORT_MODE_PC##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
                 int f = 0;
                 printmode(SPP);
                 printmode(PS2);
@@ -149,65 +151,21 @@
                 printmode(ECPPS2);
 #undef printmode
         }
- len += sprintf(page+len, "\n");
-
- len += sprintf(page+len, "mode:\t");
- if (pp->modes & PARPORT_MODE_ECR) {
- switch (r_ecr(pp) >> 5) {
- case 0:
- len += sprintf(page+len, "SPP");
- if( pp->modes & PARPORT_MODE_PS2 )
- len += sprintf(page+len, ",PS2");
- if( pp->modes & PARPORT_MODE_EPP )
- len += sprintf(page+len, ",EPP");
- break;
- case 1:
- len += sprintf(page+len, "ECPPS2");
- break;
- case 2:
- len += sprintf(page+len, "DATAFIFO");
- break;
- case 3:
- len += sprintf(page+len, "ECP");
- break;
- case 4:
- len += sprintf(page+len, "ECPEPP");
- break;
- case 5:
- len += sprintf(page+len, "Reserved?");
- break;
- case 6:
- len += sprintf(page+len, "TEST");
- break;
- case 7:
- len += sprintf(page+len, "Configuration");
- break;
- }
- } else {
- len += sprintf(page+len, "SPP");
- if (pp->modes & PARPORT_MODE_PS2)
- len += sprintf(page+len, ",PS2");
- if (pp->modes & PARPORT_MODE_EPP)
- len += sprintf(page+len, ",EPP");
- }
- len += sprintf(page+len, "\n");
-#endif
-#if 0
- /* Now no detection, please fix with an external function */
- len += sprintf(page+len, "chipset:\tunknown\n");
-#endif
-#ifdef PARPORT_INCLUDE_BENCHMARK
- if (pp->speed)
- len += sprintf(page+len, "bench:\t%d Bytes/s\n",pp->speed);
- else
- len += sprintf(page+len, "bench:\tunknown\n");
-#endif
+ page[len++] = '\n';
 
         *start = 0;
         *eof = 1;
         return len;
 }
 
+static inline void destroy_proc_entry(struct proc_dir_entry *root,
+ struct proc_dir_entry **d)
+{
+ proc_unregister(root, (*d)->low_ino);
+ kfree(*d);
+ *d = NULL;
+}
+
 static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
                                              struct proc_dir_entry *parent,
                                              unsigned short ino)
@@ -217,6 +175,7 @@
         ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
         if (!ent)
                 return NULL;
+
         memset(ent, 0, sizeof(struct proc_dir_entry));
         
         if (mode == S_IFDIR)
@@ -224,11 +183,11 @@
         else if (mode == 0)
                 mode = S_IFREG | S_IRUGO;
 
-
         ent->low_ino = ino;
         ent->name = name;
         ent->namelen = strlen(name);
         ent->mode = mode;
+
         if (S_ISDIR(mode))
                 ent->nlink = 2;
         else
@@ -240,103 +199,95 @@
 }
 
 
-int parport_proc_init()
+int parport_proc_init(void)
 {
         base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT);
 
- if (base)
- return 1;
- else {
- printk(KERN_ERR "parport: Error creating proc entry /proc/parport\n");
+ if (base == NULL) {
+ printk(KERN_ERR "Unable to initialise /proc/parport.\n");
                 return 0;
         }
+
+ return 1;
 }
 
-int parport_proc_cleanup()
+void parport_proc_cleanup(void)
 {
- if (base)
- proc_unregister(&proc_root,base->low_ino);
-
+ if (base) proc_unregister(&proc_root,base->low_ino);
         base = NULL;
-
- return 0;
 }
 
 int parport_proc_register(struct parport *pp)
 {
- struct proc_dir_entry *ent;
- static int conta=0;
- char *name;
+ static const char *proc_msg = KERN_ERR "%s: Trouble with /proc.\n";
 
- memset(&pp->pdir,0,sizeof(struct parport_dir));
+ memset(&pp->pdir, 0, sizeof(struct parport_dir));
 
- if (!base) {
- printk(KERN_ERR "parport: Error entry /proc/parport, not generated?\n");
+ if (base == NULL) {
+ printk(KERN_ERR "parport_proc not initialised yet.\n");
                 return 1;
         }
         
- name = pp->pdir.name;
- sprintf(name,"%d",conta++);
+ strncpy(pp->pdir.name, pp->name + strlen("parport"),
+ sizeof(pp->pdir.name));
 
- ent = new_proc_entry(name, S_IFDIR, base,0);
- if (!ent) {
- printk(KERN_ERR "parport: Error registering proc_entry /proc/%s\n",name);
+ pp->pdir.entry = new_proc_entry(pp->pdir.name, S_IFDIR, base, 0);
+ if (pp->pdir.entry == NULL) {
+ printk(proc_msg, pp->name);
                 return 1;
         }
- pp->pdir.entry = ent;
 
- ent = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, pp->pdir.entry,0);
- if (!ent) {
- printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/irq\n",name);
+ pp->pdir.irq = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR,
+ pp->pdir.entry, 0);
+ if (pp->pdir.irq == NULL) {
+ printk(proc_msg, pp->name);
+ destroy_proc_entry(base, &pp->pdir.entry);
                 return 1;
         }
- ent->read_proc = irq_read_proc;
- ent->write_proc= irq_write_proc;
- ent->data = pp;
- pp->pdir.irq = ent;
+ pp->pdir.irq->read_proc = irq_read_proc;
+ pp->pdir.irq->write_proc = irq_write_proc;
+ pp->pdir.irq->data = pp;
         
- ent = new_proc_entry("devices", 0, pp->pdir.entry,0);
- if (!ent) {
- printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/devices\n",name);
+ pp->pdir.devices = new_proc_entry("devices", 0, pp->pdir.entry, 0);
+ if (pp->pdir.devices == NULL) {
+ printk(proc_msg, pp->name);
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+ destroy_proc_entry(base, &pp->pdir.entry);
                 return 1;
         }
- ent->read_proc = devices_read_proc;
- ent->data = pp;
- pp->pdir.devices = ent;
+ pp->pdir.devices->read_proc = devices_read_proc;
+ pp->pdir.devices->data = pp;
         
- ent = new_proc_entry("hardware", 0, pp->pdir.entry,0);
- if (!ent) {
- printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/hardware\n",name);
+ pp->pdir.hardware = new_proc_entry("hardware", 0, pp->pdir.entry, 0);
+ if (pp->pdir.hardware == NULL) {
+ printk(proc_msg, pp->name);
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+ destroy_proc_entry(base, &pp->pdir.entry);
                 return 1;
         }
- ent->read_proc = hardware_read_proc;
- ent->data = pp;
- pp->pdir.hardware = ent;
+ pp->pdir.hardware->read_proc = hardware_read_proc;
+ pp->pdir.hardware->data = pp;
+
         return 0;
 }
 
 int parport_proc_unregister(struct parport *pp)
 {
         if (pp->pdir.entry) {
- if (pp->pdir.irq) {
- proc_unregister(pp->pdir.entry, pp->pdir.irq->low_ino);
- kfree(pp->pdir.irq);
- }
+ if (pp->pdir.irq)
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
                 
- if (pp->pdir.devices) {
- proc_unregister(pp->pdir.entry,
- pp->pdir.devices->low_ino);
- kfree(pp->pdir.devices);
- }
+ if (pp->pdir.devices)
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
                 
- if (pp->pdir.hardware) {
- proc_unregister(pp->pdir.entry,
- pp->pdir.hardware->low_ino);
- kfree(pp->pdir.hardware);
- }
+ if (pp->pdir.hardware)
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.hardware);
+
+ if (pp->pdir.probe)
+ destroy_proc_entry(pp->pdir.entry, &pp->pdir.probe);
                 
- proc_unregister(base, pp->pdir.entry->low_ino);
- kfree(pp->pdir.entry);
+ destroy_proc_entry(base, &pp->pdir.entry);
         }
         
         return 0;
Index: drivers/pnp/parport_probe.c
===================================================================
RCS file: /disks/c7/repository/linux/drivers/pnp/parport_probe.c,v
retrieving revision 1.5
diff -u -r1.5 parport_probe.c
--- parport_probe.c 1997/12/07 16:32:44 1.5
+++ parport_probe.c 1997/12/28 20:16:39
@@ -58,7 +58,11 @@
         for (i=0; ; i++) {
                 parport_write_control(port, parport_read_control(port) | 2); /* AutoFeed high */
                 if (parport_wait_peripheral(port, 0x40, 0)) {
+#ifdef DEBUG_PROBE
+ /* Some peripherals just time out when they've sent
+ all their data. */
                         printk("%s: read1 timeout.\n", port->name);
+#endif
                         parport_write_control(port, parport_read_control(port) & ~2);
                         break;
                 }
@@ -68,16 +72,18 @@
                         printk("%s: read2 timeout.\n", port->name);
                         break;
                 }
- if (( i & 1) != 0) {
- Byte= (Byte | z<<4);
+ if ((i & 1) != 0) {
+ Byte |= (z<<4);
                         if (temp)
                                 *(temp++) = Byte;
                         if (count++ == length)
                                 temp = NULL;
                         /* Does the error line indicate end of data? */
- if ((parport_read_status(port) & LP_PERRORP) == LP_PERRORP)
+ if ((parport_read_status(port) & LP_PERRORP) ==
+ LP_PERRORP)
                                 break;
- } else Byte=z;
+ } else
+ Byte=z;
         }
         read_terminate(port);
         return count;
Index: include/linux/parport.h
===================================================================
RCS file: /disks/c7/repository/linux/include/linux/parport.h,v
retrieving revision 1.4
diff -u -r1.4 parport.h
--- parport.h 1997/11/08 14:30:07 1.4
+++ parport.h 1997/12/28 22:02:36
@@ -29,6 +29,7 @@
         union {
                 struct pc_parport_state pc;
                 /* ARC has no state. */
+ /* AX uses sams state information as PC */
                 void *misc;
         } u;
 };
@@ -150,12 +151,14 @@
         struct parport_state *state; /* saved status over preemption */
 };
 
+/* Directory information for the /proc interface */
 struct parport_dir {
         struct proc_dir_entry *entry; /* Directory /proc/parport/X */
- struct proc_dir_entry *irq; /* IRQ entry /proc/parport/X/irq */
- struct proc_dir_entry *devices; /* /proc/parport/X/devices */
- struct proc_dir_entry *hardware; /* /proc/parport/X/hardware */
- char name[4]; /* /proc/parport/"XXXX" */
+ struct proc_dir_entry *irq; /* .../irq */
+ struct proc_dir_entry *devices; /* .../devices */
+ struct proc_dir_entry *hardware; /* .../hardware */
+ struct proc_dir_entry *probe; /* .../autoprobe */
+ char name[4];
 };
 
 /* A parallel port */
@@ -190,14 +193,14 @@
                                       struct parport_operations *ops);
 
 /* Unregister a port. */
-void parport_unregister_port(struct parport *port);
+extern void parport_unregister_port(struct parport *port);
 
 /* parport_in_use returns nonzero if there are devices attached to a port. */
 #define parport_in_use(x) ((x)->devices != NULL)
 
 /* Put a parallel port to sleep; release its hardware resources. Only possible
  * if no devices are registered. */
-void parport_quiesce(struct parport *);
+extern void parport_quiesce(struct parport *);
 
 /* parport_enumerate returns a pointer to the linked list of all the ports
  * in this machine.
@@ -219,13 +222,13 @@
                           int flags, void *handle);
 
 /* parport_unregister unlinks a device from the chain. */
-void parport_unregister_device(struct pardevice *dev);
+extern void parport_unregister_device(struct pardevice *dev);
 
 /* parport_claim tries to gain ownership of the port for a particular driver.
  * This may fail (return non-zero) if another driver is busy. If this
  * driver has registered an interrupt handler, it will be enabled.
  */
-int parport_claim(struct pardevice *dev);
+extern int parport_claim(struct pardevice *dev);
 
 /* parport_release reverses a previous parport_claim. This can never fail,
  * though the effects are undefined (except that they are bad) if you didn't
@@ -235,7 +238,7 @@
  * If you mess with the port state (enabling ECP for example) you should
  * clean up before releasing the port.
  */
-void parport_release(struct pardevice *dev);
+extern void parport_release(struct pardevice *dev);
 
 /* The "modes" entry in parport is a bit field representing the following
  * modes.
@@ -262,7 +265,7 @@
 
 /* Prototypes from parport_procfs */
 extern int parport_proc_init(void);
-extern int parport_proc_cleanup(void);
+extern void parport_proc_cleanup(void);
 extern int parport_proc_register(struct parport *pp);
 extern int parport_proc_unregister(struct parport *pp);
 

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