Messages in this thread Patch in this message | | | Date | Tue, 15 Apr 1997 11:05:55 +0000 (GMT) | From | Philip Blundell <> | Subject | patches for 2.1.34 |
| |
Here are some patches against 2.1.34 to fix the remaining problems with parport and merge Jose's /proc code. If all seems well I'll send them to Linus for 2.1.35.
Enjoy. p.
Index: linux/Makefile diff -u linux/Makefile:1.6 linux/Makefile:1.6.2.1 --- linux/Makefile:1.6 Tue Apr 15 00:28:38 1997 +++ linux/Makefile Tue Apr 15 11:54:33 1997 @@ -118,7 +118,8 @@ FILESYSTEMS =fs/filesystems.a NETWORKS =net/network.a DRIVERS =drivers/block/block.a \ - drivers/char/char.a + drivers/char/char.a \ + drivers/pnp/pnp.a LIBS =$(TOPDIR)/lib/lib.a SUBDIRS =kernel drivers mm fs net ipc lib @@ -142,10 +143,6 @@ ifdef CONFIG_PCI DRIVERS := $(DRIVERS) drivers/pci/pci.a -endif - -ifdef CONFIG_PNP -DRIVERS := $(DRIVERS) drivers/pnp/pnp.a endif ifdef CONFIG_SBUS Index: linux/drivers/Makefile diff -u linux/drivers/Makefile:1.2 linux/drivers/Makefile:1.2.6.1 --- linux/drivers/Makefile:1.2 Fri Apr 11 16:12:46 1997 +++ linux/drivers/Makefile Tue Apr 15 11:56:03 1997 @@ -7,17 +7,12 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -SUB_DIRS := block char net #streams +SUB_DIRS := block char net pnp #streams MOD_SUB_DIRS := $(SUB_DIRS) sbus ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp ifdef CONFIG_PCI SUB_DIRS += pci -endif - -ifdef CONFIG_PNP -SUB_DIRS += pnp -MOD_SUB_DIRS += pnp endif ifdef CONFIG_SBUS Index: linux/drivers/pnp/BUGS-parport diff -u linux/drivers/pnp/BUGS-parport:1.2 linux/drivers/pnp/BUGS-parport:1.2.6.1 --- linux/drivers/pnp/BUGS-parport:1.2 Fri Apr 11 16:12:57 1997 +++ linux/drivers/pnp/BUGS-parport Tue Apr 15 11:56:13 1997 @@ -1,8 +1,6 @@ Currently known (or at least suspected) bugs in parport: -o /proc/parport is buggy under 2.0.29 (ls /proc/parport/0 gives no such - file or directory). David has suggested a fix for this. [/proc/parport - has been temporarily taken out] +o /proc/parport is untested under 2.0.XX o SCSI aborts for PPA under 2.0.29 [reported by jmr]. Under investigation. Index: linux/drivers/pnp/TODO-parport diff -u linux/drivers/pnp/TODO-parport:1.2 linux/drivers/pnp/TODO-parport:1.2.6.1 --- linux/drivers/pnp/TODO-parport:1.2 Fri Apr 11 16:12:58 1997 +++ linux/drivers/pnp/TODO-parport Tue Apr 15 11:56:13 1997 @@ -2,31 +2,9 @@ 0. Fix the bugs (see BUGS-parport). -1. Write a /proc interface for parport. As a starting point, we could - probably have something like this: +1. Proper documentation. - /proc/parport/N/hardware - - Details of the port hardware - chipset, capabilities and so on. - Read-only. - - /proc/parport/N/irq - - IRQ number of the port. Read-write. - - /proc/parport/N/devices - - List of devices connected to this bus, with the currently active - one marked in some way. Probably you'd have the device in the - first column, and '*' (for the current device) or '-' (for a - lurker) in the second column. - - NOTE: The directory structure has been coded -- but the files are - missing ... - -2. Proper documentation. - -3. Overhaul lp.c: +2. Overhaul lp.c: a) It's a mess, and there is a lot of code duplication. @@ -40,4 +18,4 @@ bits when they have something to say. We should read out and deal with (maybe just log) whatever the printer wants to tell the world. -4. Assimilate more drivers. +3. Assimilate more drivers. Index: linux/drivers/pnp/parport_init.c diff -u linux/drivers/pnp/parport_init.c:1.3 linux/drivers/pnp/parport_init.c:1.3.2.1 --- linux/drivers/pnp/parport_init.c:1.3 Tue Apr 15 00:29:15 1997 +++ linux/drivers/pnp/parport_init.c Tue Apr 15 11:56:13 1997 @@ -1,4 +1,4 @@ -/* $Id: parport_init.c,v 1.3 1997/04/14 23:29:15 phil Exp $ +/* $Id: parport_init.c,v 1.3.2.1 1997/04/15 10:56:13 phil Exp $ * Parallel-port initialisation code. * * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> @@ -76,7 +76,7 @@ return dma; } -static int parport_detect_dma_transfer(int dma,int size) +static int parport_detect_dma_transfer(int dma,int size,int *resid) { int i,n,retv; int count=0; @@ -88,6 +88,7 @@ clear_dma_ff(i); n = get_dma_residue(i); if (n != size) { + *resid = n; retv = i; if (count > 0) { retv = -1; /* Multiple DMA's */ @@ -149,7 +150,7 @@ if( retv != -1 ) return retv; - buff = kmalloc(16, GFP_KERNEL | GFP_DMA); + buff = kmalloc(2048, GFP_KERNEL | GFP_DMA); if( !buff ){ printk("parport: memory squezze\n"); return -1; @@ -160,11 +161,12 @@ w_ecr(pb, 0xc0); /* ECP MODE */ w_ctr(pb, dsr_read ); - dma=parport_prepare_dma(buff,8); + dma=parport_prepare_dma(buff,1000); w_ecr(pb, 0xd8); /* ECP FIFO + enable DMA */ parport_enable_dma(dma); - udelay(30); /* Give some for DMA tranfer */ - retv = parport_detect_dma_transfer(dma,8); + udelay(500); /* Give some for DMA tranfer */ + retv = parport_detect_dma_transfer(dma,1000,&pb->speed); + pb->speed = pb->speed * 2000; /* 500uSec * 2000 = 1sec */ /* * National Semiconductors only supports DMA tranfers @@ -173,11 +175,12 @@ if( retv == -1 ){ w_ecr(pb, 0x60); /* ECP MODE */ w_ctr(pb, dsr_read ); - dma=parport_prepare_dma(buff,8); + dma=parport_prepare_dma(buff,1000); w_ecr(pb, 0x68); /* ECP FIFO + enable DMA */ parport_enable_dma(dma); - udelay(30); /* Give some for DMA tranfer */ - retv = parport_detect_dma_transfer(dma,8); + udelay(500); /* Give some for DMA tranfer */ + retv = parport_detect_dma_transfer(dma,1000,&pb->speed); + pb->speed = pb->speed * 2000; /* 500uSec * 2000 = 1sec */ } kfree(buff); @@ -506,7 +509,7 @@ } /* - * It's called only if supports EPP on National Semiconductors + * 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) @@ -738,17 +741,20 @@ struct parport *pb; printk(KERN_INFO "Parallel port sharing: %s\n", - "$Revision: 1.3 $"); + "$Revision: 1.3.2.1 $"); if (io[0] == -2) return 1; - /* Register /proc/parport */ - parport_proc_register(NULL); +#ifdef CONFIG_PROC_FS + parport_proc_init(); +#endif /* Run probes to ensure parport does exist */ #define PORT(a,b,c) \ if ((pb = parport_register_port((a), (b), (c)))) \ parport_destroy(pb); + + if (io[0]) { /* If the user specified any ports, use them */ int i; @@ -764,8 +770,12 @@ } #ifdef CONFIG_PNP_PARPORT_AUTOPROBE - for (pb = parport_enumerate(); pb; pb = pb->next) + for (pb = parport_enumerate(); pb; pb = pb->next) { parport_probe_one(pb); +#ifdef CONFIG_PROC_FS + parport_proc_register(pb); +#endif + } #endif return 0; @@ -784,7 +794,7 @@ kfree(port); } - parport_proc_unregister(NULL); + parport_proc_cleanup(); } #endif Index: linux/drivers/pnp/parport_procfs.c diff -u linux/drivers/pnp/parport_procfs.c:1.3 linux/drivers/pnp/parport_procfs.c:1.3.2.1 --- linux/drivers/pnp/parport_procfs.c:1.3 Tue Apr 15 00:29:16 1997 +++ linux/drivers/pnp/parport_procfs.c Tue Apr 15 11:56:14 1997 @@ -1,4 +1,4 @@ -/* $Id: parport_procfs.c,v 1.3 1997/04/14 23:29:16 phil Exp $ +/* $Id: parport_procfs.c,v 1.3.2.1 1997/04/15 10:56:14 phil Exp $ * Parallel port /proc interface code. * * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> @@ -26,103 +26,305 @@ #endif #include <linux/parport.h> +#include "parport_ll_io.h" -#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; + struct ppd *pd; + + if(count > 4 ) { /* more than 4 digits for a irq 0x?? 0?? ?? */ + return(-EOVERFLOW); + } + + 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 >= 0 ) { + free_irq(pp->irq, pp); + } + pp->irq = newirq; + 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; + len = sprintf(page, "%d\n",pp->irq); + + *start = 0; + *eof = 1; + return len; +} + +static int devices_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + 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 long long proc_parportlseek(struct inode * inode, struct file * file, - long long offset, int orig) +static int hardware_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - switch (orig) { + struct parport *pp = (struct parport *)data; + int len=0; + + len += sprintf(page+len, "base\t:\t0x%x\n",pp->base); + len += sprintf(page+len, "irq\t:\t%d\n",pp->irq); + len += sprintf(page+len, "dma\t:\t%d\n",pp->dma); + + len += sprintf(page+len, "modes\t:\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:\t"); + if( pp->modes & PARPORT_MODE_ECR ){ + switch( r_ecr(pp) >> 5 ){ case 0: - file->f_pos = offset; - return(file->f_pos); + 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: - file->f_pos += offset; - return(file->f_pos); + len += sprintf(page+len, "ECPPS2"); + break; case 2: - return(-EINVAL); - default: - return(-EINVAL); + 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"); + + /* Now no detection, please fix with an external function */ + len += sprintf(page+len, "chipset\t:\tunknown\n"); + if( pp->speed ) + len += sprintf(page+len, "bench\t:\t%d Bytes/s\n",pp->speed); + else + len += sprintf(page+len, "bench\t:\tunknown\n"); + + *start = 0; + *eof = 1; + return len; } -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 -}; -#endif +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("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); +#if defined(CONFIG_PROC_FS) + struct proc_dir_entry *ent; + static int conta=0; + char *name; + + memset(&pp->pdir,0,sizeof(struct parport_dir)); + + if( !base ){ + printk("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("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("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("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("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; #else 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 defined(CONFIG_PROC_FS) + 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; } + + Index: linux/drivers/pnp/parport_share.c diff -u linux/drivers/pnp/parport_share.c:1.3 linux/drivers/pnp/parport_share.c:1.3.2.1 --- linux/drivers/pnp/parport_share.c:1.3 Tue Apr 15 00:29:16 1997 +++ linux/drivers/pnp/parport_share.c Tue Apr 15 11:56:14 1997 @@ -1,4 +1,4 @@ -/* $Id: parport_share.c,v 1.3 1997/04/14 23:29:16 phil Exp $ +/* $Id: parport_share.c,v 1.3.2.1 1997/04/15 10:56:14 phil Exp $ * Parallel-port resource manager code. * * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> @@ -36,7 +36,7 @@ return portlist; } -static void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs) +void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs) { /* NULL function - Does nothing */ return; Index: linux/include/linux/parport.h diff -u linux/include/linux/parport.h:1.2 linux/include/linux/parport.h:1.2.6.1 --- linux/include/linux/parport.h:1.2 Fri Apr 11 16:13:17 1997 +++ linux/include/linux/parport.h Tue Apr 15 12:01:07 1997 @@ -1,10 +1,11 @@ -/* $Id: parport.h,v 1.2 1997/04/11 15:13:17 phil Exp $ */ +/* $Id: parport.h,v 1.2.6.1 1997/04/15 11:01:07 phil Exp $ */ #ifndef _PARPORT_H_ #define _PARPORT_H_ #include <asm/system.h> #include <asm/ptrace.h> +#include <linux/proc_fs.h> /* Maximum of 8 ports per machine */ #define PARPORT_MAX 8 @@ -78,6 +79,14 @@ struct ppd *prev; }; +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" */ +}; + /* A parallel port */ struct parport { unsigned int base; /* base address */ @@ -93,8 +102,9 @@ unsigned int ecr; /* ECP ECR register */ struct parport *next; unsigned int flags; - struct proc_dir_entry *proc_dir; + struct parport_dir pdir; struct parport_device_info probe_info; + int speed; /* Max Write in Bytes/s */ }; /* parport_register_port registers a new parallel port at the given address (if @@ -174,8 +184,10 @@ char); /* Prototypes from parport_procfs */ +extern int parport_proc_init(void); +extern int parport_proc_cleanup(void); extern int parport_proc_register(struct parport *pp); -extern void parport_proc_unregister(struct parport *pp); +extern int parport_proc_unregister(struct parport *pp); /* Prototypes from parport_ksyms.c */ extern void dec_parport_count(void);
| |