patch-2.1.36 linux/drivers/pnp/parport_procfs.c

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

diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/parport_procfs.c linux/drivers/pnp/parport_procfs.c
@@ -1,4 +1,4 @@
-/* $Id: parport_procfs.c,v 1.1.2.2 1997/03/26 17:50:36 phil Exp $
+/* $Id: parport_procfs.c,v 1.3.2.6 1997/04/16 21:30:38 phil Exp $
  * Parallel port /proc interface code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
@@ -21,108 +21,320 @@
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 
-#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
-#endif
 
 #include <linux/parport.h>
+#include "parport_ll_io.h"
+
+#undef PARPORT_INCLUDE_BENCH
 
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
+struct proc_dir_entry *base=NULL;
 
-/************************************************/
-static long proc_readparport(struct inode * inode, struct file * file,
-							 char * buf, unsigned long count)
+void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
+
+static int irq_write_proc(struct file *file, const char *buffer,
+					  unsigned long count, void *data)
 {
-	printk("proc_readparport\n");
-	return 0;
+	int newirq;
+	struct parport *pp = (struct parport *)data;
+	
+	if (count > 4 )  /* more than 4 digits 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);
+			else
+				newirq = simple_strtoul(&buffer[1],0,8);
+		} else {
+			newirq = simple_strtoul(buffer,0,10);
+		}
+	}
+
+	if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) 
+		free_irq(pp->irq, pp);
+
+	pp->irq = newirq;
+
+	if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) { 
+		struct ppd *pd = pp->cad;
+
+		if (pd == NULL) {
+			pd = pp->devices;
+			if (pd != NULL) 
+				request_irq(pp->irq, pd->irq_func ? 
+					    pd->irq_func :
+					    parport_null_intr_func,
+					    SA_INTERRUPT, pd->name, pd->port);
+		} else {
+			request_irq(pp->irq, pd->irq_func ? pd->irq_func :
+				    parport_null_intr_func,
+				    SA_INTERRUPT, pp->name, pd->port);
+		}
+	}
+
+	return count;
 }
 
-static long proc_writeparport(struct inode * inode, struct file * file,
-							  const char * buf, unsigned long count)
+static int irq_read_proc(char *page, char **start, off_t off,
+					 int count, int *eof, void *data)
 {
-	printk("proc_writeparport\n");
+	struct parport *pp = (struct parport *)data;
+	int len;
 	
-	return 0;
+	if (pp->irq == PARPORT_IRQ_NONE)
+		len = sprintf(page, "none\n");
+	else
+		len = sprintf(page, "%d\n", pp->irq);
+	
+	*start = 0;
+	*eof   = 1;
+	return len;
 }
 
-static long long proc_parportlseek(struct inode * inode, struct file * file, 
-				long long offset, int orig)
+static int devices_read_proc(char *page, char **start, off_t off,
+					 int count, int *eof, void *data)
 {
-    switch (orig) {
-    case 0:
-	file->f_pos = offset;
-	return(file->f_pos);
-    case 1:
-	file->f_pos += offset;
-	return(file->f_pos);
-    case 2:
-	return(-EINVAL);
-    default:
-	return(-EINVAL);
-    }
-}
-
-static struct file_operations proc_dir_operations = {
-    proc_parportlseek,	/* lseek   */
-    proc_readparport,	/* read	   */
-    proc_writeparport,	/* write   */
-    proc_readdir,	    /* readdir */
-    NULL,		/* poll    */
-    NULL,		/* ioctl   */
-    NULL,		/* mmap	   */
-    NULL,		/* no special open code	   */
-    NULL,		/* no special release code */
-    NULL		/* can't fsync */
-};
-
-/************************************************/
-static struct inode_operations parport_proc_dir_inode_operations = {
-	&proc_dir_operations,	/* default net directory file-ops */
-	NULL,			/* create */
-	proc_lookup,	/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	NULL,			/* truncate */
-	NULL			/* permission */
-};
-
-static struct proc_dir_entry proc_root_parport = {
-	PROC_PARPORT, 7, "parport",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-	0, &parport_proc_dir_inode_operations,
-	NULL, NULL,
-	NULL, &proc_root, NULL,
-	NULL, NULL
-};
+	struct parport *pp = (struct parport *)data;
+	struct ppd *pd1;
+	int len=0;
+
+	for (pd1 = pp->devices; pd1 ; pd1 = pd1->next) {
+		if (pd1 == pp->cad)
+			len += sprintf(page+len, "+");
+		else
+			len += sprintf(page+len, " ");
+
+		len += sprintf(page+len, "%s",pd1->name);
+
+		if (pd1 == pp->lurker)
+			len += sprintf(page+len, " LURK");
+		
+		len += sprintf(page+len,"\n");
+	}
+		
+	*start = 0;
+	*eof   = 1;
+	return len;
+}
+
+static int hardware_read_proc(char *page, char **start, off_t off,
+							  int count, int *eof, void *data)
+{
+	struct parport *pp = (struct parport *)data;
+	int len=0;
+	
+	len += sprintf(page+len, "base:\t0x%x\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);
+	len += sprintf(page+len, "dma:\t%d\n",pp->dma);
+
+	len += sprintf(page+len, "modes:\t");
+	{
+#define printmode(x) {if(pp->modes&PARPORT_MODE_##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
+		int f = 0;
+		printmode(SPP);
+		printmode(PS2);
+		printmode(EPP);
+		printmode(ECP);
+		printmode(ECPEPP);
+		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");
+	
+#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	
+
+	*start = 0;
+	*eof   = 1;
+	return len;
+}
+
+static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
+					     struct proc_dir_entry *parent,
+					     unsigned short ino)
+{
+	struct proc_dir_entry *ent;
+
+	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)
+		mode |= S_IRUGO | S_IXUGO;
+	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
+		ent->nlink = 1;
+
+	proc_register(parent, ent);
+	
+	return ent;
+}
+
+
+int parport_proc_init()
+{
+	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");
+		return 0;
+	}
+}
+
+int parport_proc_cleanup()
+{
+	if (base)
+		proc_unregister(&proc_root,base->low_ino);
+
+	base = NULL;
+	
+	return 0;
+}
 
 int parport_proc_register(struct parport *pp)
 {
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
-	return proc_register(&proc_root, &proc_root_parport);
-#else
+	struct proc_dir_entry *ent;
+	static int conta=0;
+	char *name;
+
+	memset(&pp->pdir,0,sizeof(struct parport_dir));
+
+	if (!base) {
+		printk(KERN_ERR "parport: Error entry /proc/parport, not generated?\n");
+		return 1;
+	}
+	
+	name = pp->pdir.name;
+	sprintf(name,"%d",conta++);
+
+	ent = new_proc_entry(name, S_IFDIR, base,0);
+	if (!ent) {
+		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s\n",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);
+		return 1;
+	}
+	ent->read_proc = irq_read_proc;
+	ent->write_proc= irq_write_proc;
+	ent->data      = pp;
+	pp->pdir.irq   = ent;
+	
+	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);
+		return 1;
+	}
+	ent->read_proc   = devices_read_proc;
+	ent->data        = pp;
+	pp->pdir.devices = ent;
+	
+	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);
+		return 1;
+	}
+	ent->read_proc    = hardware_read_proc;
+	ent->data         = pp;
+	pp->pdir.hardware = ent;
 	return 0;
-#endif
 }
 
-void parport_proc_unregister(struct parport *pp)
+int parport_proc_unregister(struct parport *pp)
 {
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
-	if( pp ){
-		proc_unregister(&proc_root_parport, pp->proc_dir->low_ino);
-		kfree(pp->proc_dir);
-	}else{
-		proc_unregister(&proc_root, proc_root_parport.low_ino);
+	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.devices) {
+			proc_unregister(pp->pdir.entry,
+					pp->pdir.devices->low_ino);
+			kfree(pp->pdir.devices);
+		}
+		
+		if (pp->pdir.hardware) {
+			proc_unregister(pp->pdir.entry,
+					pp->pdir.hardware->low_ino);
+			kfree(pp->pdir.hardware);
+		}
+		
+		proc_unregister(base, pp->pdir.entry->low_ino);
+		kfree(pp->pdir.entry);
 	}
-#endif
+	
+	return 0;
 }

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