patch-2.1.82 linux/drivers/misc/parport_procfs.c

Next file: linux/drivers/misc/parport_share.c
Previous file: linux/drivers/misc/parport_pc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.81/linux/drivers/misc/parport_procfs.c linux/drivers/misc/parport_procfs.c
@@ -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);
 
@@ -36,24 +33,28 @@
 	int newirq;
 	struct parport *pp = (struct parport *)data;
 	
-	if (count > 4 )  /* more than 4 digits for a irq 0x?? 0?? ??  */
-		return(-EOVERFLOW);
+	if (count > 5 )  /* more than 4 digits + \n for a irq 0x?? 0?? ??  */
+		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,13 @@
 
 	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,"\n");
+		page[len++] = '\n';
 	}
 		
 	*start = 0;
@@ -120,26 +119,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 +148,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 +172,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 +180,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 +196,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;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov