diff options
Diffstat (limited to 'drivers')
49 files changed, 1440 insertions, 349 deletions
diff --git a/drivers/block/README.fd b/drivers/block/README.fd index 3ceb16c0b..d05120c59 100644 --- a/drivers/block/README.fd +++ b/drivers/block/README.fd @@ -179,6 +179,13 @@ floppy=fifo Uses a less noisy way to clear the disk change line (which doesn't involve seeks). Implied by daring. + floppy=<nr>,irq + Sets the floppy IRQ to <nr> instead of 6 + + floppy=<nr>,dma + Sets the floppy DMA channel to <nr> instead of 2 + + Supporting utilities and additional documentation: ================================================== diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 7a08808f2..77add0b3a 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1981,7 +1981,7 @@ static int floppy_release( struct inode * inode, struct file * filp ) if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT))) /* if the file is mounted OR (writable now AND writable at open time) Linus: Does this cover all cases? */ - block_fsync (inode, filp); + block_fsync (filp, filp->f_dentry); if (fd_ref[drive] < 0) fd_ref[drive] = 0; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 04ea60ff8..7af5aeee1 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3502,7 +3502,7 @@ static int floppy_release(struct inode * inode, struct file * filp) if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT))) /* if the file is mounted OR (writable now AND writable at * open time) Linus: Does this cover all cases? */ - block_fsync(inode,filp); + block_fsync(filp, filp->f_dentry); if (UDRS->fd_ref < 0) UDRS->fd_ref=0; @@ -3865,6 +3865,9 @@ static struct param_table { { "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */ { "asus_pci", 0, &allowed_drive_mask, 0x33, 0}, + { "irq", 0, &FLOPPY_IRQ, 6, 0 }, + { "dma", 0, &FLOPPY_DMA, 2, 0 }, + { "daring", daring, 0, 1, 0}, { "two_fdc", 0, &FDC2, 0x370, 0 }, diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index 25b3d54fa..ddaf1b0c6 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-probe.c Version 1.01 Jan 26, 1997 + * linux/drivers/block/ide-probe.c Version 1.02 Jul 29, 1997 * * Copyright (C) 1994-1996 Linus Torvalds & authors (see below) */ @@ -38,6 +38,8 @@ * * Version 1.00 move drive probing code from ide.c to ide-probe.c * Version 1.01 fix compilation problem for m68k + * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot + * by Andrea Arcangeli <arcangeli@mbox.queen.it> */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ diff --git a/drivers/block/ide.h b/drivers/block/ide.h index ecfdc12ea..eb3f54a55 100644 --- a/drivers/block/ide.h +++ b/drivers/block/ide.h @@ -158,7 +158,8 @@ typedef unsigned char byte; /* used everywhere */ #else #define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */ #endif /* CONFIG_APM */ -#define WAIT_PIDENTIFY (1*HZ) /* 1sec - should be less than 3ms (?) */ +#define WAIT_PIDENTIFY (10*HZ) /* 10sec - should be less than 3ms (?) + if all ATAPI CD is closed at boot */ #define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */ #define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */ #define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */ diff --git a/drivers/block/rd.c b/drivers/block/rd.c index b8239df9b..759dbbca8 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -360,7 +360,7 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) * Read block 0 to test for gzipped kernel */ if (fp->f_op->llseek) - fp->f_op->llseek(fp->f_dentry->d_inode, fp, start_block * BLOCK_SIZE, 0); + fp->f_op->llseek(fp, start_block * BLOCK_SIZE, 0); fp->f_pos = start_block * BLOCK_SIZE; fp->f_op->read(fp->f_dentry->d_inode, fp, buf, size); @@ -390,8 +390,7 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) * Read block 1 to test for minix and ext2 superblock */ if (fp->f_op->llseek) - fp->f_op->llseek(fp->f_dentry->d_inode, fp, - (start_block+1) * BLOCK_SIZE, 0); + fp->f_op->llseek(fp, (start_block+1) * BLOCK_SIZE, 0); fp->f_pos = (start_block+1) * BLOCK_SIZE; fp->f_op->read(fp->f_dentry->d_inode, fp, buf, size); @@ -421,7 +420,7 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) done: if (fp->f_op->llseek) - fp->f_op->llseek(fp->f_dentry->d_inode, fp, start_block * BLOCK_SIZE, 0); + fp->f_op->llseek(fp, start_block * BLOCK_SIZE, 0); fp->f_pos = start_block * BLOCK_SIZE; if ((nblocks > 0) && blk_size[MAJOR(device)]) { diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 4dc442673..12be2e362 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -842,7 +842,7 @@ static int floppy_release(struct inode *inode, struct file *filp) return -ENXIO; fs = &floppy_states[0]; if (filp == 0 || (filp->f_mode & (2 | OPEN_WRITE_BIT))) - block_fsync(inode, filp); + block_fsync(filp, filp->f_dentry); sw = fs->swim3; if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); diff --git a/drivers/char/amigamouse.c b/drivers/char/amigamouse.c index 602695c39..6977d2398 100644 --- a/drivers/char/amigamouse.c +++ b/drivers/char/amigamouse.c @@ -159,11 +159,10 @@ static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp) MSE_INT_ON(); } -static int fasync_mouse(struct inode *inode, struct file *filp, int on) +static int fasync_mouse(struct file *filp, int on) { int retval; - - retval = fasync_helper(inode, filp, on, &mouse.fasyncptr); + retval = fasync_helper(filp, on, &mouse.fasyncptr); if (retval < 0) return retval; return 0; @@ -175,7 +174,7 @@ static int fasync_mouse(struct inode *inode, struct file *filp, int on) static int release_mouse(struct inode * inode, struct file * file) { - fasync_mouse(inode, file, 0); + fasync_mouse(file, 0); if (--mouse.active) return 0; free_irq(IRQ_AMIGA_VERTB, mouse_interrupt); diff --git a/drivers/char/apm_bios.c b/drivers/char/apm_bios.c index 67ec582e4..565600738 100644 --- a/drivers/char/apm_bios.c +++ b/drivers/char/apm_bios.c @@ -13,7 +13,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * $Id: apm_bios.c,v 1.1.1.1 1997/06/01 03:17:29 ralf Exp $ + * $Id: apm_bios.c,v 1.2 1997/09/12 01:31:41 ralf Exp $ * * October 1995, Rik Faith (faith@cs.unc.edu): * Minor enhancements and updates (to the patch set) for 1.3.x @@ -958,7 +958,7 @@ static int do_open(struct inode * inode, struct file * filp) as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL); if (as == NULL) { - printk(KERN_ERR "apm_bios: cannot allocate struct of size %d bytes", + printk(KERN_ER "apm_bios: cannot allocate struct of size %d bytes", sizeof(*as)); return -ENOMEM; } diff --git a/drivers/char/atarimouse.c b/drivers/char/atarimouse.c index 950cb1546..2641c9834 100644 --- a/drivers/char/atarimouse.c +++ b/drivers/char/atarimouse.c @@ -54,11 +54,10 @@ static void atari_mouse_interrupt(char *buf) /* ikbd_mouse_rel_pos(); */ } -static int fasync_mouse(struct inode *inode, struct file *filp, int on) +static int fasync_mouse(struct file *filp, int on) { int retval; - - retval = fasync_helper(inode, filp, on, &mouse.fasyncptr); + retval = fasync_helper(filp, on, &mouse.fasyncptr); if (retval < 0) return retval; return 0; @@ -66,7 +65,7 @@ static int fasync_mouse(struct inode *inode, struct file *filp, int on) static int release_mouse(struct inode *inode, struct file *file) { - fasync_mouse(inode, file, 0); + fasync_mouse(file, 0); if (--mouse.active) return 0; ikbd_mouse_disable(); diff --git a/drivers/char/atixlmouse.c b/drivers/char/atixlmouse.c index c8a730a35..7ffee43bc 100644 --- a/drivers/char/atixlmouse.c +++ b/drivers/char/atixlmouse.c @@ -95,11 +95,10 @@ void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs) ATIXL_MSE_ENABLE_UPDATE(); } -static int fasync_mouse(struct inode *inode, struct file *filp, int on) +static int fasync_mouse(struct file *filp, int on) { int retval; - - retval = fasync_helper(inode, filp, on, &mouse.fasync); + retval = fasync_helper(filp, on, &mouse.fasync); if (retval < 0) return retval; return 0; @@ -107,7 +106,7 @@ static int fasync_mouse(struct inode *inode, struct file *filp, int on) static int release_mouse(struct inode * inode, struct file * file) { - fasync_mouse(inode, file, 0); + fasync_mouse(file, 0); if (--mouse.active) return 0; ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */ diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index 3e2ee97bd..9e160cb93 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -106,11 +106,12 @@ static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) MSE_INT_ON(); } -static int fasync_mouse(struct inode *inode, struct file *filp, int on) +static int fasync_mouse(struct file *filp, int on) { int retval; + struct inode *inode = filp->f_dentry->d_inode; - retval = fasync_helper(inode, filp, on, &mouse.fasyncptr); + retval = fasync_helper(filp, on, &mouse.fasyncptr); if (retval < 0) return retval; return 0; @@ -122,7 +123,7 @@ static int fasync_mouse(struct inode *inode, struct file *filp, int on) static int close_mouse(struct inode * inode, struct file * file) { - fasync_mouse(inode, file, 0); + fasync_mouse(file, 0); if (--mouse.active) return 0; MSE_INT_OFF(); diff --git a/drivers/char/fbmem.c b/drivers/char/fbmem.c index 4a5bea195..d475413b3 100644 --- a/drivers/char/fbmem.c +++ b/drivers/char/fbmem.c @@ -199,10 +199,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } } -static int -fb_mmap(struct inode *inode, struct file *file, struct vm_area_struct * vma) +static int fb_mmap(struct file *file, struct vm_area_struct * vma) { - struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)]; + struct fb_ops *fb = registered_fb[GET_FB_IDX(file->f_dentry->d_inode->i_rdev)]; struct fb_fix_screeninfo fix; if (! fb) diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 270159480..f18d25d9a 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -129,8 +129,7 @@ typedef struct { } stlconf_t; static stlconf_t stli_brdconf[] = { - /*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/ - { BRD_ECP, 0x2b0, 0, 0xcc000, 0, 0 }, + { BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 }, }; static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t); @@ -168,7 +167,7 @@ static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t); * all the local structures required by a serial tty driver. */ static char *stli_drvname = "Stallion Intelligent Multiport Serial Driver"; -static char *stli_drvversion = "5.3.2"; +static char *stli_drvversion = "5.3.4"; static char *stli_serialname = "ttyE"; static char *stli_calloutname = "cue"; @@ -447,6 +446,7 @@ int stli_eisaprobe = STLI_EISAPROBE; #define ECH_PNLSTATUS 2 #define ECH_PNL16PORT 0x20 #define ECH_PNLIDMASK 0x07 +#define ECH_PNLXPID 0x40 #define ECH_PNLINTRPEND 0x80 /* @@ -542,12 +542,12 @@ static void stli_flushbuffer(struct tty_struct *tty); static void stli_hangup(struct tty_struct *tty); static inline int stli_initbrds(void); -static int stli_brdinit(stlibrd_t *brdp); static inline int stli_initecp(stlibrd_t *brdp); static inline int stli_initonb(stlibrd_t *brdp); -static int stli_eisamemprobe(stlibrd_t *brdp); static inline int stli_findeisabrds(void); static inline int stli_initports(stlibrd_t *brdp); +static int stli_eisamemprobe(stlibrd_t *brdp); +static int stli_brdinit(stlibrd_t *brdp); static int stli_startbrd(stlibrd_t *brdp); static long stli_memread(struct inode *ip, struct file *fp, char *buf, unsigned long count); static long stli_memwrite(struct inode *ip, struct file *fp, const char *buf, unsigned long count); @@ -3341,7 +3341,7 @@ static inline int stli_initecp(stlibrd_t *brdp) cdkecpsig_t sig; cdkecpsig_t *sigsp; unsigned int status, nxtid; - int panelnr; + int panelnr, nrports; #if DEBUG printk("stli_initecp(brdp=%x)\n", (int) brdp); @@ -3448,16 +3448,13 @@ static inline int stli_initecp(stlibrd_t *brdp) status = sig.panelid[nxtid]; if ((status & ECH_PNLIDMASK) != nxtid) break; - if (status & ECH_PNL16PORT) { - brdp->panels[panelnr] = 16; - brdp->nrports += 16; - nxtid += 2; - } else { - brdp->panels[panelnr] = 8; - brdp->nrports += 8; - nxtid++; - } brdp->panelids[panelnr] = status; + nrports = (status & ECH_PNL16PORT) ? 16 : 8; + if ((nrports == 16) && ((status & ECH_PNLXPID) == 0)) + nxtid++; + brdp->panels[panelnr] = nrports; + brdp->nrports += nrports; + nxtid++; brdp->nrpanels++; } diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 770607df4..49a6c65db 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -27,6 +27,7 @@ #include <linux/fcntl.h> #include <linux/delay.h> +#include <asm/irq.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -103,7 +104,13 @@ static int lp_reset(int minor) return r_str(minor); } -static inline int lp_char_polled(char lpchar, int minor) +static inline int must_use_polling(int minor) +{ + return lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE || + lp_table[minor].dev->port->devices->next; +} + +static inline int lp_char(char lpchar, int minor, int use_polling) { int status; unsigned int wait = 0; @@ -115,12 +122,13 @@ static inline int lp_char_polled(char lpchar, int minor) count++; if (need_resched) lp_schedule (minor); - } while (!LP_READY(minor, status) && count < LP_CHAR(minor)); + } while (((use_polling && !LP_READY(minor, status)) || + (!use_polling && !(status & LP_PBUSY))) && + (count < LP_CHAR(minor))); - if (count == LP_CHAR(minor)) { + if (count == LP_CHAR(minor) || + (!use_polling && !LP_CAREFUL_READY(minor, status))) return 0; - /* we timed out, and the character was /not/ printed */ - } w_dtr(minor, lpchar); stats = &LP_STAT(minor); stats->chars++; @@ -150,50 +158,6 @@ static inline int lp_char_polled(char lpchar, int minor) return 1; } -static inline int lp_char_interrupt(char lpchar, int minor) -{ - unsigned int wait; - unsigned long count = 0; - unsigned char status; - struct lp_stats *stats; - - do { - if(need_resched) - lp_schedule (minor); - if ((status = r_str(minor)) & LP_PBUSY) { - if (!LP_CAREFUL_READY(minor, status)) - 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. */ - wait = 0; - while (wait != LP_WAIT(minor)) /* FIXME: should be */ - wait++; /* a udelay () */ - /* control port takes strobe high */ - w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE); - while (wait) - wait--; /* FIXME: should be a udelay() */ - /* take strobe low */ - w_ctr(minor, LP_PSELECP | LP_PINITP); - /* update waittime statistics */ - if (count) { - if (count > stats->maxwait) - stats->maxwait = count; - count *= 256; - wait = (count > stats->meanwait) ? count - stats->meanwait : - stats->meanwait - count; - stats->meanwait = (255 * stats->meanwait + count + 128) / 256; - stats->mdev = ((127 * stats->mdev) + wait + 64) / 128; - } - return 1; - } - } while (count++ < LP_CHAR(minor)); - - return 0; -} - static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct parport *pb = (struct parport *) dev_id; @@ -204,7 +168,16 @@ static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs) wake_up(&lp_dev->lp_wait_q); } -static inline int lp_write_interrupt(unsigned int minor, const char *buf, int count) +static void lp_error(int minor) +{ + if (must_use_polling(minor)) { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + LP_TIMEOUT_POLLED; + lp_schedule (minor); + } +} + +static inline int lp_write_buf(unsigned int minor, const char *buf, int count) { unsigned long copy_size; unsigned long total_bytes_written = 0; @@ -223,7 +196,7 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co copy_from_user(lp->lp_buffer, buf, copy_size); while (copy_size) { - if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) { + if (lp_char(lp->lp_buffer[bytes_written], minor, must_use_polling(minor))) { --copy_size; ++bytes_written; lp_table[minor].runchars++; @@ -236,32 +209,48 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co 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++; - cli(); - enable_irq(lp->dev->port->irq); - w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN); - status = r_str(minor); - if ((!(status & LP_PACK) || (status & LP_PBUSY)) - && LP_CAREFUL_READY(minor, status)) { + + if (must_use_polling(minor)) { +#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(); + enable_irq(lp->dev->port->irq); + w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN); + status = r_str(minor); + if ((!(status & LP_PACK) || (status & LP_PBUSY)) + && LP_CAREFUL_READY(minor, status)) { + w_ctr(minor, LP_PSELECP | LP_PINITP); + 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(); - 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 (current->signal & ~current->blocked) { if (total_bytes_written + bytes_written) return total_bytes_written + bytes_written; @@ -280,72 +269,6 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co return total_bytes_written; } -static inline int lp_write_polled(unsigned int minor, const char *buf, int count) -{ - int retval, status; - char c; - const char *temp; - - temp = buf; - while (count > 0) { - get_user(c, temp); - retval = lp_char_polled(c, minor); - /* only update counting vars if character was printed */ - if (retval) { - count--; temp++; - lp_table[minor].runchars++; - } else { /* if printer timed out */ - 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 temp-buf?temp-buf:-ENOSPC; - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + LP_TIMEOUT_POLLED; - lp_schedule (minor); - } else - if (!(status & LP_PSELECD)) { - printk(KERN_INFO "lp%d off-line\n", minor); - if(LP_F(minor) & LP_ABORT) - return temp-buf?temp-buf:-EIO; - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + LP_TIMEOUT_POLLED; - lp_schedule (minor); - } else - /* not offline or out of paper. on fire? */ - if (!(status & LP_PERRORP)) { - printk(KERN_ERR "lp%d on fire\n", minor); - if(LP_F(minor) & LP_ABORT) - return temp-buf?temp-buf:-EIO; - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + LP_TIMEOUT_POLLED; - lp_schedule (minor); - } - - /* check for signals before going to sleep */ - if (current->signal & ~current->blocked) { - if (temp != buf) - return temp-buf; - else - return -EINTR; - } - LP_STAT(minor).sleeps++; -#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); - } - } - return temp-buf; -} - static long lp_write(struct inode * inode, struct file * file, const char * buf, unsigned long count) { @@ -362,17 +285,13 @@ static long lp_write(struct inode * inode, struct file * file, */ lp_parport_claim (minor); - if (LP_IRQ(minor) > 0) - retv = lp_write_interrupt(minor, buf, count); - else - retv = lp_write_polled(minor, buf, count); + retv = lp_write_buf(minor, buf, count); lp_parport_release (minor); return retv; } -static long long lp_lseek(struct inode * inode, struct file * file, - long long offset, int origin) +static long long lp_lseek(struct file * file, long long offset, int origin) { return -ESPIPE; } @@ -432,7 +351,7 @@ static long lp_read(struct inode * inode, struct file * file, udelay(50); counter++; if (need_resched) - lp_schedule (minor); + schedule (); } while ( (status == 0x40) && (counter < 20) ); if ( counter == 20 ) { /* Timeout */ #ifdef LP_READ_DEBUG @@ -451,7 +370,7 @@ static long lp_read(struct inode * inode, struct file * file, udelay(20); counter++; if (need_resched) - lp_schedule (minor); + schedule (); } while ( (status == 0) && (counter < 20) ); if (counter == 20) { /* Timeout */ #ifdef LP_READ_DEBUG @@ -467,7 +386,7 @@ static long lp_read(struct inode * inode, struct file * file, } current->state=TASK_INTERRUPTIBLE; current->timeout=jiffies + LP_TIME(minor); - lp_schedule (minor); + schedule (); } counter=0; if (( i & 1) != 0) { @@ -517,12 +436,10 @@ static int lp_open(struct inode * inode, struct file * file) return -EIO; } } - if (LP_IRQ(minor) > 0) { - lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); - if (!lp_table[minor].lp_buffer) { - MOD_DEC_USE_COUNT; - return -ENOMEM; - } + lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); + if (!lp_table[minor].lp_buffer) { + MOD_DEC_USE_COUNT; + return -ENOMEM; } LP_F(minor) |= LP_BUSY; return 0; @@ -531,12 +448,9 @@ static int lp_open(struct inode * inode, struct file * file) static int lp_release(struct inode * inode, struct file * file) { unsigned int minor = MINOR(inode->i_rdev); - unsigned int irq; - if ((irq = LP_IRQ(minor)) != PARPORT_IRQ_NONE) { - kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); - lp_table[minor].lp_buffer = NULL; - } + kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); + lp_table[minor].lp_buffer = NULL; LP_F(minor) &= ~LP_BUSY; MOD_DEC_USE_COUNT; return 0; diff --git a/drivers/char/lp_m68k.c b/drivers/char/lp_m68k.c index 117dc3fe7..bdb3405ca 100644 --- a/drivers/char/lp_m68k.c +++ b/drivers/char/lp_m68k.c @@ -353,8 +353,7 @@ static long lp_write(struct inode *inode, struct file *file, } #endif -static long long lp_lseek(struct inode * inode, struct file * file, - long long offset, int origin) +static long long lp_lseek(struct file * file, long long offset, int origin) { return -ESPIPE; } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 78df2e3be..94c207e10 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -117,7 +117,7 @@ static long write_mem(struct inode * inode, struct file * file, return do_write_mem(file,__va(p),p,buf,count); } -static int mmap_mem(struct inode * inode, struct file * file, struct vm_area_struct * vma) +static int mmap_mem(struct file * file, struct vm_area_struct * vma) { unsigned long offset = vma->vm_offset; @@ -330,7 +330,7 @@ out: return written ? written : -EFAULT; } -static int mmap_zero(struct inode * inode, struct file * file, struct vm_area_struct * vma) +static int mmap_zero(struct file * file, struct vm_area_struct * vma) { if (vma->vm_flags & VM_SHARED) return -EINVAL; @@ -350,8 +350,7 @@ static long write_full(struct inode * inode, struct file * file, * both devices with "a" now. This was previously impossible. SRB. */ -static long long null_lseek(struct inode * inode, struct file * file, - long long offset, int orig) +static long long null_lseek(struct file * file, long long offset, int orig) { return file->f_pos=0; } @@ -363,8 +362,7 @@ static long long null_lseek(struct inode * inode, struct file * file, * also note that seeking relative to the "end of file" isn't supported: * it has no meaning, so it returns -EINVAL. */ -static long long memory_lseek(struct inode * inode, struct file * file, - long long offset, int orig) +static long long memory_lseek(struct file * file, long long offset, int orig) { switch (orig) { case 0: diff --git a/drivers/char/msbusmouse.c b/drivers/char/msbusmouse.c index 8f98231b8..a8c32ce6d 100644 --- a/drivers/char/msbusmouse.c +++ b/drivers/char/msbusmouse.c @@ -89,11 +89,11 @@ static void ms_mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs) } } -static int fasync_mouse(struct inode *inode, struct file *filp, int on) +static int fasync_mouse(struct file *filp, int on) { int retval; - retval = fasync_helper(inode, filp, on, &mouse.fasyncptr); + retval = fasync_helper(filp, on, &mouse.fasyncptr); if (retval < 0) return retval; return 0; @@ -101,7 +101,7 @@ static int fasync_mouse(struct inode *inode, struct file *filp, int on) static int release_mouse(struct inode * inode, struct file * file) { - fasync_mouse(inode, file, 0); + fasync_mouse(file, 0); if (--mouse.active) return 0; MS_MSE_INT_OFF(); diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c new file mode 100644 index 000000000..402981749 --- /dev/null +++ b/drivers/char/nvram.c @@ -0,0 +1,695 @@ +/* + * CMOS/NV-RAM driver for Linux + * + * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> + * idea by and with help from Richard Jelinek <rj@suse.de> + * + * This driver allows you to access the contents of the non-volatile memory in + * the mc146818rtc.h real-time clock. This chip is built into all PCs and into + * many Atari machines. In the former it's called "CMOS-RAM", in the latter + * "NVRAM" (NV stands for non-volatile). + * + * The data are supplied as a (seekable) character device, /dev/nvram. The + * size of this file is 50, the number of freely available bytes in the memory + * (i.e., not used by the RTC itself). + * + * Checksums over the NVRAM contents are managed by this driver. In case of a + * bad checksum, reads and writes return -EIO. The checksum can be initialized + * to a sane state either by ioctl(NVRAM_INIT) (clear whole NVRAM) or + * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid + * again; use with care!) + * + * This file also provides some functions for other parts of the kernel that + * want to access the NVRAM: nvram_{read,write,check_checksum,set_checksum}. + * Obviously this can be used only if this driver is always configured into + * the kernel and is not a module. Since the functions are used by some Atari + * drivers, this is the case on the Atari. + * + */ + +#define NVRAM_VERSION "1.0" + +#include <linux/module.h> +#include <linux/config.h> + +#define PC 1 +#define ATARI 2 + +/* select machine configuration */ +#if defined(CONFIG_ATARI) +#define MACH ATARI +#elif defined(__i386__) /* and others?? */ +#define MACH PC +#else +#error Cannot build nvram driver for this machine configuration. +#endif + +#if MACH == PC + +/* RTC in a PC */ +#define CHECK_DRIVER_INIT() 1 + +/* On PCs, the checksum is built only over bytes 2..31 */ +#define PC_CKS_RANGE_START 2 +#define PC_CKS_RANGE_END 31 +#define PC_CKS_LOC 32 + +#define mach_check_checksum pc_check_checksum +#define mach_set_checksum pc_set_checksum +#define mach_proc_infos pc_proc_infos + +#endif + +#if MACH == ATARI + +/* Special parameters for RTC in Atari machines */ +#include <asm/atarihw.h> +#include <asm/atariints.h> +#define RTC_PORT(x) (TT_RTC_BAS + 2*(x)) +#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK)) + +/* On Ataris, the checksum is over all bytes except the checksum bytes + * themselves; these are at the very end */ +#define ATARI_CKS_RANGE_START 0 +#define ATARI_CKS_RANGE_END 47 +#define ATARI_CKS_LOC 48 + +#define mach_check_checksum atari_check_checksum +#define mach_set_checksum atari_set_checksum +#define mach_proc_infos atari_proc_infos + +#endif + +/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with + * interrupts disabled. Due to the index-port/data-port design of the RTC, we + * don't want two different things trying to get to it at once. (e.g. the + * periodic 11 min sync from time.c vs. this driver.) + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/miscdevice.h> +#include <linux/malloc.h> +#include <linux/ioport.h> +#include <linux/fcntl.h> +#include <linux/mc146818rtc.h> +#include <linux/nvram.h> +#include <linux/init.h> +#ifdef CONFIG_PROC_FS +#include <linux/proc_fs.h> +#endif + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> + + +static int nvram_open_cnt = 0; /* #times opened */ +static int nvram_open_mode; /* special open modes */ +#define NVRAM_WRITE 1 /* opened for writing (exclusive) */ +#define NVRAM_EXCL 2 /* opened with O_EXCL */ + +#define RTC_FIRST_BYTE 14 /* RTC register number of first NVRAM byte */ +#define NVRAM_BYTES 50 /* number of NVRAM bytes */ + + +static int mach_check_checksum( void ); +static void mach_set_checksum( void ); +#ifdef CONFIG_PROC_FS +static int mach_proc_infos( unsigned char *contents, char *buffer, int *len, + off_t *begin, off_t offset, int size ); +#endif + + +/* + * These are the internal NVRAM access functions, which do NOT disable + * interrupts and do not check the checksum. Both tasks are left to higher + * level function, so they need to be done only once per syscall. + */ + +static __inline__ unsigned char nvram_read_int( int i ) +{ + return( CMOS_READ( RTC_FIRST_BYTE+i ) ); +} + +static __inline__ void nvram_write_int( unsigned char c, int i ) +{ + CMOS_WRITE( c, RTC_FIRST_BYTE+i ); +} + +static __inline__ int nvram_check_checksum_int( void ) +{ + return( mach_check_checksum() ); +} + +static __inline__ void nvram_set_checksum_int( void ) +{ + mach_set_checksum(); +} + +#if MACH == ATARI + +/* + * These non-internal functions are provided to be called by other parts of + * the kernel. It's up to the caller to ensure correct checksum before reading + * or after writing (needs to be done only once). + * + * They're only built if CONFIG_ATARI is defined, because Atari drivers use + * them. For other configurations (PC), the rest of the kernel can't rely on + * them being present (this driver couldn't be configured at all, or as a + * module), so they access config information themselves. + */ + +unsigned char nvram_read_byte( int i ) +{ + unsigned long flags; + unsigned char c; + + save_flags(flags); + cli(); + c = nvram_read_int( i ); + restore_flags(flags); + return( c ); +} + +void nvram_write_byte( unsigned char c, int i ) +{ + unsigned long flags; + + save_flags(flags); + cli(); + nvram_write_int( c, i ); + restore_flags(flags); +} + +int nvram_check_checksum( void ) +{ + unsigned long flags; + int rv; + + save_flags(flags); + cli(); + rv = nvram_check_checksum_int(); + restore_flags(flags); + return( rv ); +} + +void nvram_set_checksum( void ) +{ + unsigned long flags; + + save_flags(flags); + cli(); + nvram_set_checksum_int(); + restore_flags(flags); +} + +#endif /* MACH == ATARI */ + + +/* + * The are the file operation function for user access to /dev/nvram + */ + +static long long nvram_llseek(struct file *file,loff_t offset, int origin ) +{ + switch( origin ) { + case 0: + /* nothing to do */ + break; + case 1: + offset += file->f_pos; + break; + case 2: + offset += NVRAM_BYTES; + break; + } + return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL ); +} + +static long nvram_read( struct inode * inode, struct file * file, + char * buf, unsigned long count ) +{ + unsigned long flags; + unsigned i = file->f_pos; + char *tmp = buf; + + save_flags(flags); + cli(); + + if (!nvram_check_checksum_int()) { + restore_flags(flags); + return( -EIO ); + } + + for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) + put_user( nvram_read_int(i), tmp ); + file->f_pos = i; + + restore_flags(flags); + return( tmp - buf ); +} + +static long nvram_write( struct inode * inode, struct file * file, + const char * buf, unsigned long count ) +{ + unsigned long flags; + unsigned i = file->f_pos; + const char *tmp = buf; + char c; + + save_flags(flags); + cli(); + + if (!nvram_check_checksum_int()) { + restore_flags(flags); + return( -EIO ); + } + + for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) { + get_user( c, tmp ); + nvram_write_int( c, i ); + } + nvram_set_checksum_int(); + file->f_pos = i; + + restore_flags(flags); + return( tmp - buf ); +} + +static int nvram_ioctl( struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg ) +{ + unsigned long flags; + int i; + + switch( cmd ) { + + case NVRAM_INIT: /* initialize NVRAM contents and checksum */ + if (!suser()) + return( -EACCES ); + + save_flags(flags); + cli(); + + for( i = 0; i < NVRAM_BYTES; ++i ) + nvram_write_int( 0, i ); + nvram_set_checksum_int(); + + restore_flags(flags); + return( 0 ); + + case NVRAM_SETCKS: /* just set checksum, contents unchanged + * (maybe useful after checksum garbaged + * somehow...) */ + if (!suser()) + return( -EACCES ); + + save_flags(flags); + cli(); + nvram_set_checksum_int(); + restore_flags(flags); + return( 0 ); + + default: + return( -EINVAL ); + } +} + +static int nvram_open( struct inode *inode, struct file *file ) +{ + if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || + (nvram_open_mode & NVRAM_EXCL) || + ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) + return( -EBUSY ); + + if (file->f_flags & O_EXCL) + nvram_open_mode |= NVRAM_EXCL; + if (file->f_mode & 2) + nvram_open_mode |= NVRAM_WRITE; + nvram_open_cnt++; + MOD_INC_USE_COUNT; + return( 0 ); +} + +static int nvram_release( struct inode *inode, struct file *file ) +{ + nvram_open_cnt--; + if (file->f_flags & O_EXCL) + nvram_open_mode &= ~NVRAM_EXCL; + if (file->f_mode & 2) + nvram_open_mode &= ~NVRAM_WRITE; + + MOD_DEC_USE_COUNT; + return( 0 ); +} + + +#ifdef CONFIG_PROC_FS + +struct proc_dir_entry *proc_nvram; + +static int nvram_read_proc( char *buffer, char **start, off_t offset, + int size, int *eof, void *data ) +{ + unsigned long flags; + unsigned char contents[NVRAM_BYTES]; + int i, len = 0; + off_t begin = 0; + + save_flags(flags); + cli(); + for( i = 0; i < NVRAM_BYTES; ++i ) + contents[i] = nvram_read_int( i ); + restore_flags(flags); + + *eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size ); + + if (offset >= begin + len) + return( 0 ); + *start = buffer + (begin - offset); + return( size < begin + len - offset ? size : begin + len - offset ); + +} + +/* This macro frees the machine specific function from bounds checking and + * this like that... */ +#define PRINT_PROC(fmt,args...) \ + do { \ + *len += sprintf( buffer+*len, fmt, ##args ); \ + if (*begin + *len > offset + size) \ + return( 0 ); \ + if (*begin + *len < offset) { \ + *begin += *len; \ + *len = 0; \ + } \ + } while(0) + +#endif + +static struct file_operations nvram_fops = { + nvram_llseek, + nvram_read, + nvram_write, + NULL, /* No readdir */ + NULL, /* No poll */ + nvram_ioctl, + NULL, /* No mmap */ + nvram_open, + nvram_release +}; + +static struct miscdevice nvram_dev = { + NVRAM_MINOR, + "nvram", + &nvram_fops +}; + + +__initfunc(int nvram_init(void)) +{ + /* First test whether the driver should init at all */ + if (!CHECK_DRIVER_INIT()) + return( -ENXIO ); + + printk( "Non-volatile memory driver v%s\n", NVRAM_VERSION ); + misc_register( &nvram_dev ); +#ifdef CONFIG_PROC_FS + if ((proc_nvram = create_proc_entry( "nvram", 0, 0 ))) + proc_nvram->read_proc = nvram_read_proc; +#endif + + return( 0 ); +} + +#ifdef MODULE +int init_module (void) +{ + return( nvram_init() ); +} + +void cleanup_module (void) +{ +#ifdef CONFIG_PROC_FS + if (proc_nvram) + remove_proc_entry( "nvram", 0 ); +#endif + misc_deregister( &nvram_dev ); +} +#endif + + +/* + * Machine specific functions + */ + + +#if MACH == PC + +static int pc_check_checksum( void ) +{ + int i; + unsigned short sum = 0; + + for( i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i ) + sum += nvram_read_int( i ); + return( (sum & 0xffff) == + ((nvram_read_int(PC_CKS_LOC) << 8) | + nvram_read_int(PC_CKS_LOC+1)) ); +} + +static void pc_set_checksum( void ) +{ + int i; + unsigned short sum = 0; + + for( i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i ) + sum += nvram_read_int( i ); + nvram_write_int( sum >> 8, PC_CKS_LOC ); + nvram_write_int( sum & 0xff, PC_CKS_LOC+1 ); +} + +#ifdef CONFIG_PROC_FS + +static char *floppy_types[] = { + "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M" +}; + +static char *gfx_types[] = { + "EGA, VGA, ... (with BIOS)", + "CGA (40 cols)", + "CGA (80 cols)", + "monochrome", +}; + +static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len, + off_t *begin, off_t offset, int size ) +{ + unsigned long flags; + int checksum; + int type; + + save_flags(flags); + cli(); + checksum = nvram_check_checksum_int(); + restore_flags(flags); + + PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " ); + + PRINT_PROC( "# floppies : %d\n", + (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0 ); + PRINT_PROC( "Floppy 0 type : " ); + type = nvram[2] >> 4; + if (type < sizeof(floppy_types)/sizeof(*floppy_types)) + PRINT_PROC( "%s\n", floppy_types[type] ); + else + PRINT_PROC( "%d (unknown)\n", type ); + PRINT_PROC( "Floppy 1 type : " ); + type = nvram[2] & 0x0f; + if (type < sizeof(floppy_types)/sizeof(*floppy_types)) + PRINT_PROC( "%s\n", floppy_types[type] ); + else + PRINT_PROC( "%d (unknown)\n", type ); + + PRINT_PROC( "HD 0 type : " ); + type = nvram[4] >> 4; + if (type) + PRINT_PROC( " %02x\n", type == 0x0f ? nvram[11] : type ); + else + PRINT_PROC( "none\n" ); + + PRINT_PROC( "HD 1 type : " ); + type = nvram[4] & 0x0f; + if (type) + PRINT_PROC( " %02x\n", type == 0x0f ? nvram[12] : type ); + else + PRINT_PROC( "none\n" ); + + PRINT_PROC( "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", + nvram[18] | (nvram[19] << 8), + nvram[20], nvram[25], + nvram[21] | (nvram[22] << 8), + nvram[23] | (nvram[24] << 8) ); + PRINT_PROC( "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", + nvram[39] | (nvram[40] << 8), + nvram[41], nvram[46], + nvram[42] | (nvram[43] << 8), + nvram[44] | (nvram[45] << 8) ); + + PRINT_PROC( "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8) ); + PRINT_PROC( "Extended memory: %d kB (configured), %d kB (tested)\n", + nvram[9] | (nvram[10] << 8), + nvram[34] | (nvram[35] << 8) ); + + PRINT_PROC( "Gfx adapter : %s\n", gfx_types[ (nvram[6] >> 4)&3 ] ); + + PRINT_PROC( "FPU : %sinstalled\n", + (nvram[6] & 2) ? "" : "not " ); + + return( 1 ); +} +#endif + +#endif /* MACH == PC */ + +#if MACH == ATARI + +static int atari_check_checksum( void ) +{ + int i; + unsigned char sum = 0; + + for( i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i ) + sum += nvram_read_int( i ); + return( nvram_read_int( ATARI_CKS_LOC ) == (~sum & 0xff) && + nvram_read_int( ATARI_CKS_LOC+1 ) == (sum & 0xff) ); +} + +static void atari_set_checksum( void ) +{ + int i; + unsigned char sum = 0; + + for( i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i ) + sum += nvram_read_int( i ); + nvram_write_int( ~sum, ATARI_CKS_LOC ); + nvram_write_int( sum, ATARI_CKS_LOC+1 ); +} + +#ifdef CONFIG_PROC_FS + +static struct { + unsigned char val; + char *name; +} boot_prefs[] = { + { 0x80, "TOS" }, + { 0x40, "ASV" }, + { 0x20, "NetBSD (?)" }, + { 0x10, "Linux" }, + { 0x00, "unspecified" } +}; + +static char *languages[] = { + "English (US)", + "German", + "French", + "English (UK)", + "Spanish", + "Italian", + "6 (undefined)", + "Swiss (French)", + "Swiss (German)" +}; + +static char *dateformat[] = { + "MM%cDD%cYY", + "DD%cMM%cYY", + "YY%cMM%cDD", + "YY%cDD%cMM", + "4 (undefined)", + "5 (undefined)", + "6 (undefined)", + "7 (undefined)" +}; + +static char *colors[] = { + "2", "4", "16", "256", "65536", "??", "??", "??" +}; + +#define fieldsize(a) (sizeof(a)/sizeof(*a)) + +static int atari_proc_infos( unsigned char *nvram, char *buffer, int *len, + off_t *begin, off_t offset, int size ) +{ + int checksum = nvram_check_checksum(); + int i; + unsigned vmode; + + PRINT_PROC( "Checksum status : %svalid\n", checksum ? "" : "not " ); + + PRINT_PROC( "Boot preference : " ); + for( i = fieldsize(boot_prefs)-1; i >= 0; --i ) { + if (nvram[1] == boot_prefs[i].val) { + PRINT_PROC( "%s\n", boot_prefs[i].name ); + break; + } + } + if (i < 0) + PRINT_PROC( "0x%02x (undefined)\n", nvram[1] ); + + PRINT_PROC( "SCSI arbitration : %s\n", (nvram[16] & 0x80) ? "on" : "off" ); + PRINT_PROC( "SCSI host ID : " ); + if (nvram[16] & 0x80) + PRINT_PROC( "%d\n", nvram[16] & 7 ); + else + PRINT_PROC( "n/a\n" ); + + /* the following entries are defined only for the Falcon */ + if ((atari_mch_cookie >> 16) != ATARI_MCH_FALCON) + return; + + PRINT_PROC( "OS language : " ); + if (nvram[6] < fieldsize(languages)) + PRINT_PROC( "%s\n", languages[nvram[6]] ); + else + PRINT_PROC( "%u (undefined)\n", nvram[6] ); + PRINT_PROC( "Keyboard language: " ); + if (nvram[7] < fieldsize(languages)) + PRINT_PROC( "%s\n", languages[nvram[7]] ); + else + PRINT_PROC( "%u (undefined)\n", nvram[7] ); + PRINT_PROC( "Date format : " ); + PRINT_PROC( dateformat[nvram[8]&7], + nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/' ); + PRINT_PROC( ", %dh clock\n", nvram[8] & 16 ? 24 : 12 ); + PRINT_PROC( "Boot delay : " ); + if (nvram[10] == 0) + PRINT_PROC( "default" ); + else + PRINT_PROC( "%ds%s\n", nvram[10], + nvram[10] < 8 ? ", no memory test" : "" ); + + vmode = (nvram[14] << 8) || nvram[15]; + PRINT_PROC( "Video mode : %s colors, %d columns, %s %s monitor\n", + colors[vmode & 7], + vmode & 8 ? 80 : 40, + vmode & 16 ? "VGA" : "TV", + vmode & 32 ? "PAL" : "NTSC" ); + PRINT_PROC( " %soverscan, compat. mode %s%s\n", + vmode & 64 ? "" : "no ", + vmode & 128 ? "on" : "off", + vmode & 256 ? + (vmode & 16 ? ", line doubling" : ", half screen") : "" ); + + return( 1 ); +} +#endif + +#endif /* MACH == ATARI */ + +/* + * Local variables: + * c-indent-level: 4 + * tab-width: 4 + * End: + */ diff --git a/drivers/char/pc110pad.c b/drivers/char/pc110pad.c index d9c5ac453..71b75deb2 100644 --- a/drivers/char/pc110pad.c +++ b/drivers/char/pc110pad.c @@ -474,11 +474,11 @@ static void sample_ps2(int d[3]) -static int fasync_pad(struct inode *inode, struct file *filp, int on) +static int fasync_pad(struct file *filp, int on) { int retval; - retval = fasync_helper(inode, filp, on, &asyncptr); + retval = fasync_helper(filp, on, &asyncptr); if (retval < 0) return retval; return 0; @@ -490,7 +490,7 @@ static int fasync_pad(struct inode *inode, struct file *filp, int on) */ static int close_pad(struct inode * inode, struct file * file) { - fasync_pad(inode, file, 0); + fasync_pad(file, 0); if (--active) return 0; outb(0x30, current_params.io+2); /* switch off digitiser */ diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c index 9a77783b3..2f8a5a75b 100644 --- a/drivers/char/pcwd.c +++ b/drivers/char/pcwd.c @@ -28,6 +28,7 @@ * drivers to panic the system if it's overheating at bootup. * 961118 Changed some verbiage on some of the output, tidied up * code bits, and added compatibility to 2.1.x. + * 970912 Enabled board on open and disable on close. */ #include <linux/module.h> @@ -209,9 +210,6 @@ static void pcwd_send_heartbeat(void) { int wdrst_stat; - if (!is_open) - return; - wdrst_stat = inb_p(current_readport); wdrst_stat &= 0x0F; @@ -373,7 +371,13 @@ static long pcwd_write(struct inode *inode, struct file *file, const char *buf, static int pcwd_open(struct inode *ino, struct file *filep) { + if (is_open) + return -EIO; MOD_INC_USE_COUNT; + /* Enable the port */ + if (revision == PCWD_REVISION_C) + outb_p(0x00, current_readport + 3); + is_open = 1; return(0); } @@ -397,7 +401,15 @@ static long pcwd_read(struct inode *inode, struct file *file, char *buf, static int pcwd_close(struct inode *ino, struct file *filep) { + is_open = 0; MOD_DEC_USE_COUNT; +#ifndef CONFIG_WATCHDOG_NOWAYOUT + /* Disable the board */ + if (revision == PCWD_REVISION_C) { + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + } +#endif return 0; } @@ -531,8 +543,6 @@ __initfunc(int pcwatchdog_init(void)) } #endif - is_open = 1; - #ifdef PCWD_BLIND current_readport = PCWD_BLIND; #endif @@ -571,6 +581,11 @@ __initfunc(int pcwatchdog_init(void)) #ifdef MODULE void cleanup_module(void) { + /* Disable the board */ + if (revision == PCWD_REVISION_C) { + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + } misc_deregister(&pcwd_miscdev); if (supports_temp) misc_deregister(&temp_miscdev); diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c index e07c8648d..972f38ad3 100644 --- a/drivers/char/psaux.c +++ b/drivers/char/psaux.c @@ -104,11 +104,11 @@ static inline int queue_empty(void) return queue->head == queue->tail; } -static int fasync_aux(struct inode *inode, struct file *filp, int on) +static int fasync_aux(struct file *filp, int on) { int retval; - retval = fasync_helper(inode, filp, on, &queue->fasync); + retval = fasync_helper(filp, on, &queue->fasync); if (retval < 0) return retval; return 0; @@ -270,7 +270,7 @@ static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs) static int release_aux(struct inode * inode, struct file * file) { - fasync_aux(inode, file, 0); + fasync_aux(file, 0); if (--aux_count) return 0; aux_start_atomic(); @@ -408,7 +408,7 @@ static int release_qp(struct inode * inode, struct file * file) { unsigned char status; - fasync_aux(inode, file, 0); + fasync_aux(file, 0); if (!--qp_count) { if (!poll_qp_status()) printk("Warning: Mouse device busy in release_qp()\n"); diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 5f03f8887..b150dd7e1 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -76,8 +76,7 @@ static struct wait_queue *rtc_wait; static struct timer_list rtc_irq_timer; -static long long rtc_llseek(struct inode *inode, struct file *file, - loff_t offset, int origin); +static long long rtc_llseek(struct file *file, loff_t offset, int origin); static long rtc_read(struct inode *inode, struct file *file, char *buf, unsigned long count); @@ -142,8 +141,7 @@ static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) * Now all the various file operations that we export. */ -static long long rtc_llseek(struct inode *inode, struct file *file, - loff_t offset, int origin) +static long long rtc_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 184a21040..1ec03230b 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -102,8 +102,7 @@ typedef struct { } stlconf_t; static stlconf_t stl_brdconf[] = { - /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/ - { BRD_ECH, 0x2a0, 0x280, 0, 15, 0 }, + { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, }; static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); @@ -141,7 +140,7 @@ static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); * all the local structures required by a serial tty driver. */ static char *stl_drvname = "Stallion Multiport Serial Driver"; -static char *stl_drvversion = "5.3.2"; +static char *stl_drvversion = "5.3.4"; static char *stl_serialname = "ttyE"; static char *stl_calloutname = "cue"; @@ -391,9 +390,9 @@ static void stl_hangup(struct tty_struct *tty); static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); static inline int stl_initbrds(void); -static int stl_brdinit(stlbrd_t *brdp); static inline int stl_initeio(stlbrd_t *brdp); static inline int stl_initech(stlbrd_t *brdp); +static int stl_brdinit(stlbrd_t *brdp); static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp); static int stl_mapirq(int irq); static void stl_getserial(stlport_t *portp, struct serial_struct *sp); @@ -436,7 +435,8 @@ static void stl_cd1400disableintrs(stlport_t *portp); static void stl_cd1400sendbreak(stlport_t *portp, long len); static void stl_cd1400flowctrl(stlport_t *portp, int state); static void stl_cd1400flush(stlport_t *portp); -static void stl_cd1400intr(stlpanel_t *panelp, unsigned int iobase); +static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase); +static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase); static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr); static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr); static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr); @@ -519,7 +519,7 @@ static uart_t stl_cd1400uart = { stl_cd1400sendbreak, stl_cd1400flowctrl, stl_cd1400flush, - stl_cd1400intr + stl_cd1400eiointr }; /* @@ -1912,7 +1912,7 @@ static inline int stl_initeio(stlbrd_t *brdp) panelp->isr = stl_sc26198intr; } else { panelp->uartp = (void *) &stl_cd1400uart; - panelp->isr = stl_cd1400intr; + panelp->isr = stl_cd1400eiointr; } brdp->panels[0] = panelp; @@ -2053,10 +2053,8 @@ static inline int stl_initech(stlbrd_t *brdp) } } else { panelp->uartp = (void *) &stl_cd1400uart; - panelp->isr = stl_cd1400intr; + panelp->isr = stl_cd1400echintr; if (status & ECH_PNL16PORT) { - if ((brdp->nrports + 16) > 32) - break; panelp->nrports = 16; panelp->ackmask = 0x80; if (brdp->brdtype != BRD_ECHPCI) @@ -3217,15 +3215,45 @@ static void stl_cd1400flush(stlport_t *portp) /*****************************************************************************/ /* + * Interrupt service routine for cd1400 EasyIO boards. + */ + +static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) +{ + unsigned char svrtype; + +#if DEBUG + printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", (int) panelp, iobase); +#endif + + outb(SVRR, iobase); + svrtype = inb(iobase + EREG_DATA); + if (panelp->nrports > 4) { + outb((SVRR + 0x80), iobase); + svrtype |= inb(iobase + EREG_DATA); + } + + if (svrtype & SVRR_RX) + stl_cd1400rxisr(panelp, iobase); + if (svrtype & SVRR_TX) + stl_cd1400txisr(panelp, iobase); + if (svrtype & SVRR_MDM) + stl_cd1400mdmisr(panelp, iobase); +} + + +/*****************************************************************************/ + +/* * Interrupt service routine for cd1400 panels. */ -static void stl_cd1400intr(stlpanel_t *panelp, unsigned int iobase) +static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) { unsigned char svrtype; #if DEBUG - printk("stl_cd1400intr(panelp=%x,iobase=%x)\n", (int) panelp, iobase); + printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp, iobase); #endif outb(SVRR, iobase); @@ -3562,7 +3590,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) * Check that each chip is present and started up OK. */ chipmask = 0; - nrchips = panelp->nrports / SC26198_PORTS; + nrchips = (panelp->nrports + 4) / SC26198_PORTS; if (brdp->brdtype == BRD_ECHPCI) outb(panelp->pagenr, brdp->ioctrl); @@ -3778,7 +3806,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) stl_sc26198setreg(portp, IMR, 0); stl_sc26198updatereg(portp, MR0, mr0); stl_sc26198updatereg(portp, MR1, mr1); - stl_sc26198setreg(portp, CCR, CR_RXERRBLOCK); + stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK); stl_sc26198updatereg(portp, MR2, mr2); stl_sc26198updatereg(portp, IOPIOR, ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr)); @@ -3792,7 +3820,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); ipr = stl_sc26198getreg(portp, IPR); - if (ipr & MSVR1_DCD) + if (ipr & IPR_DCD) portp->sigs &= ~TIOCM_CD; else portp->sigs |= TIOCM_CD; @@ -4120,7 +4148,7 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) outb(0, (iobase + 1)); iack = inb(iobase + XP_IACK); - portp = panelp->ports[(iack & IVR_CHANMASK)]; + portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)]; if (iack & IVR_RXDATA) stl_sc26198rxisr(portp, iack); @@ -4178,7 +4206,7 @@ static void stl_sc26198txisr(stlport_t *portp) len = MIN(len, SC26198_TXFIFOSIZE); portp->stats.txtotal += len; stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); - outb((GTXFIFO | portp->uartaddr), (ioaddr + XP_ADDR)); + outb(GTXFIFO, (ioaddr + XP_ADDR)); outsb((ioaddr + XP_DATA), tail, stlen); len -= stlen; tail += stlen; @@ -4215,21 +4243,21 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) tty = portp->tty; ioaddr = portp->ioaddr; - outb((GIBCR | portp->uartaddr), (ioaddr + XP_ADDR)); + outb(GIBCR, (ioaddr + XP_ADDR)); len = inb(ioaddr + XP_DATA) + 1; if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { if ((tty == (struct tty_struct *) NULL) || (tty->flip.char_buf_ptr == (char *) NULL) || ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) { - outb((GRXFIFO | portp->uartaddr), (ioaddr + XP_ADDR)); + outb(GRXFIFO, (ioaddr + XP_ADDR)); insb((ioaddr + XP_DATA), &stl_unwanted[0], len); portp->stats.rxlost += len; portp->stats.rxtotal += len; } else { len = MIN(len, buflen); if (len > 0) { - outb((GRXFIFO | portp->uartaddr), (ioaddr + XP_ADDR)); + outb(GRXFIFO, (ioaddr + XP_ADDR)); insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len); memset(tty->flip.flag_buf_ptr, 0, len); tty->flip.flag_buf_ptr += len; @@ -4342,7 +4370,7 @@ static void stl_sc26198rxbadchars(stlport_t *portp) stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { - stl_sc26198setreg(portp, CCR, CR_CLEARRXERR); + stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR); ch = stl_sc26198getreg(portp, RXFIFO); stl_sc26198rxbadch(portp, status, ch); } diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c index 9d4ee2449..3a8d02b22 100644 --- a/drivers/char/tpqic02.c +++ b/drivers/char/tpqic02.c @@ -1,4 +1,4 @@ -/* $Id: tpqic02.c,v 1.10 1997/01/26 07:13:20 davem Exp $ +/* $Id: tpqic02.c,v 1.1.1.1 1997/06/01 03:17:28 ralf Exp $ * * Driver for tape drive support for Linux-i386 * @@ -134,8 +134,8 @@ static volatile struct mtget ioctl_status; /* current generic status */ static volatile struct tpstatus tperror; /* last drive status */ -static char rcs_revision[] = "$Revision: 1.10 $"; -static char rcs_date[] = "$Date: 1997/01/26 07:13:20 $"; +static char rcs_revision[] = "$Revision: 1.1.1.1 $"; +static char rcs_date[] = "$Date: 1997/06/01 03:17:28 $"; /* Flag bits for status and outstanding requests. * (Could all be put in one bit-field-struct.) @@ -1712,8 +1712,7 @@ static void qic02_tape_interrupt(int irq, void *dev_id, struct pt_regs *regs) } /* qic02_tape_interrupt */ -static long long qic02_tape_lseek(struct inode * inode, struct file * file, - long long offset, int origin) +static long long qic02_tape_lseek(struct file * file, long long offset, int origin) { return -EINVAL; /* not supported */ } /* qic02_tape_lseek */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 4c6ecae22..2148a06a6 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -115,7 +115,7 @@ static int tty_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); static int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); -static int tty_fasync(struct inode * inode, struct file * filp, int on); +static int tty_fasync(struct file * filp, int on); #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -327,8 +327,7 @@ static int hung_up_tty_ioctl(struct inode * inode, struct file * file, return cmd == TIOCSPGRP ? -ENOTTY : -EIO; } -static long long tty_lseek(struct inode * inode, struct file * file, - long long offset, int orig) +static long long tty_lseek(struct file * file, long long offset, int orig) { return -ESPIPE; } @@ -381,7 +380,7 @@ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops) continue; if (filp->f_op != &tty_fops) continue; - tty_fasync(filp->f_dentry->d_inode, filp, 0); + tty_fasync(filp, 0); filp->f_op = fops; } @@ -926,7 +925,7 @@ static void release_dev(struct file * filp) check_tty_count(tty, "release_dev"); - tty_fasync(filp->f_dentry->d_inode, filp, 0); + tty_fasync(filp, 0); idx = MINOR(tty->device) - tty->driver.minor_start; pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY && @@ -1263,7 +1262,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait) * to set up the fasync queue. It returns negative on error, 0 if it did * no changes and positive if it added/deleted the entry. */ -int fasync_helper(struct inode * inode, struct file * filp, int on, struct fasync_struct **fapp) +int fasync_helper(struct file * filp, int on, struct fasync_struct **fapp) { struct fasync_struct *fa, **fp; unsigned long flags; @@ -1298,27 +1297,26 @@ int fasync_helper(struct inode * inode, struct file * filp, int on, struct fasyn return 1; } -static int tty_fasync(struct inode * inode, struct file * filp, int on) +static int tty_fasync(struct file * filp, int on) { struct tty_struct * tty; int retval; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, inode->i_rdev, "tty_fasync")) + if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync")) return 0; - retval = fasync_helper(inode, filp, on, &tty->fasync); + retval = fasync_helper(filp, on, &tty->fasync); if (retval <= 0) return retval; if (on) { if (!waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = 1; - if (filp->f_owner == 0) { - if (tty->pgrp) - filp->f_owner = -tty->pgrp; - else - filp->f_owner = current->pid; + if (filp->f_owner.pid == 0) { + filp->f_owner.pid = (-tty->pgrp) ? : current->pid; + filp->f_owner.uid = current->uid; + filp->f_owner.euid = current->euid; } } else { if (!tty->fasync && !waitqueue_active(&tty->read_wait)) diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c0d7440c3..9d2ecda3a 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -79,11 +79,10 @@ vcs_size(struct inode *inode) return size; } -static long long -vcs_lseek(struct inode *inode, struct file *file, long long offset, int orig) +static long long vcs_lseek(struct file *file, long long offset, int orig) { int size; - size = vcs_size(inode); + size = vcs_size(file->f_dentry->d_inode); switch (orig) { case 0: diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index 31837eee2..cbe763975 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -155,8 +155,7 @@ void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) } -static long long wdt_llseek(struct inode *inode, struct file *file, long long offset, - int origin) +static long long wdt_llseek(struct file *file, long long offset, int origin) { return -ESPIPE; } diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index 86d8a3432..f096101d5 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.2 1997/06/03 09:24:18 ralf Exp $ +/* $Id: isdn_common.c,v 1.3 1997/09/12 01:31:49 ralf Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -21,6 +21,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_common.c,v $ + * Revision 1.3 1997/09/12 01:31:49 ralf + * Merge with Linux 2.1.55. More bugfixes and goodies from my private + * CVS archive. + * * Revision 1.2 1997/06/03 09:24:18 ralf * Sync with Linux 2.1.42. * @@ -221,7 +225,7 @@ isdn_dev *dev = (isdn_dev *) 0; -static char *isdn_revision = "$Revision: 1.2 $"; +static char *isdn_revision = "$Revision: 1.3 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -925,8 +929,7 @@ isdn_read(struct inode *inode, struct file *file, char *buf, RWARG count) return -ENODEV; } -static LSTYPE -isdn_lseek(struct inode *inode, struct file *file, LSARG offset, int orig) +static LSTYPE isdn_lseek(struct file *file, LSARG offset, int orig) { return -ESPIPE; } diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 30a7100c0..6e1f5fadf 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -86,8 +86,7 @@ static int adb_release(struct inode *inode, struct file *file) return 0; } -static long long adb_lseek(struct inode *inode, struct file *file, - long long offset, int origin) +static long long adb_lseek(struct file *file, long long offset, int origin) { return -ESPIPE; } diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c index 9bb6166e4..0f2ab2f82 100644 --- a/drivers/macintosh/nvram.c +++ b/drivers/macintosh/nvram.c @@ -12,8 +12,7 @@ #define NVRAM_SIZE 8192 -static long long nvram_llseek(struct inode *inode, struct file *file, - loff_t offset, int origin) +static long long nvram_llseek(struct file *file, loff_t offset, int origin) { switch (origin) { case 1: diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 9d568b2fd..795df5697 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -25,6 +25,10 @@ ifeq ($(CONFIG_PARPORT),y) endif ifeq ($(CONFIG_PARPORT_PC),y) LX_OBJS += parport_pc.o + else + ifeq ($(CONFIG_PARPORT_PC),m) + M_OBJS += parport_pc.o + endif endif LX_OBJS += parport_init.o else diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c index ae32bc91c..477b350e3 100644 --- a/drivers/misc/parport_pc.c +++ b/drivers/misc/parport_pc.c @@ -881,9 +881,9 @@ int parport_pc_init(int *io, int *irq, int *dma) } while (*io && (++i < PC_MAX_PORTS)); } else { /* Probe all the likely ports. */ + count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO); count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO); count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO); - count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO); } return count; } diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c index e4c58370f..6d518d284 100644 --- a/drivers/misc/parport_share.c +++ b/drivers/misc/parport_share.c @@ -33,9 +33,13 @@ static int portcount = 0; struct parport *parport_enumerate(void) { #ifdef CONFIG_KERNELD - if (portlist == NULL) + if (portlist == NULL) { request_module("parport_lowlevel"); -#endif +#ifdef CONFIG_PNP_PARPORT_MODULE + request_module("parport_probe"); +#endif /* CONFIG_PNP_PARPORT_MODULE */ + } +#endif /* CONFIG_KERNELD */ return portlist; } diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 2e721ba8d..b90affadc 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -126,7 +126,7 @@ if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then fi # -# LocalTalk +# AppleTalk # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_ATALK" != "n" ]; then @@ -136,6 +136,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Dayna firmware support' CONFIG_COPS_DAYNA bool 'Tangent firmware support' CONFIG_COPS_TANGENT fi + dep_tristate 'IP-over-DDP driver support' CONFIG_IPDDP $CONFIG_ATALK fi fi @@ -202,10 +203,10 @@ fi # # WAN drivers support # -if [ "$CONFIG_WAN_ROUTER" = "y" ]; then +if [ "$CONFIG_WAN_ROUTER" != "n" ]; then bool 'WAN drivers' CONFIG_WAN_DRIVERS if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then - bool 'Sangoma WANPIPE(tm) multiprotocol cards' CONFIG_VENDOR_SANGOMA + dep_tristate 'Sangoma WANPIPE(tm) multiprotocol cards' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS if [ "$CONFIG_VENDOR_SANGOMA" = "y" ]; then int ' Maximum number of cards' CONFIG_WANPIPE_CARDS 1 bool ' WANPIPE X.25 support' CONFIG_WANPIPE_X25 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 920c17dc2..a79d7b4ea 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -727,6 +727,14 @@ else endif endif +ifeq ($(CONFIG_IPDDP),y) +L_OBJS += ipddp.o +else + ifeq ($(CONFIG_IPDDP),m) + M_OBJS += ipddp.o + endif +endif + ifeq ($(CONFIG_BAYCOM),y) L_OBJS += baycom.o CONFIG_HDLCDRV_BUILTIN = y diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 4fdfbb6b1..b568c12bf 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -326,6 +326,17 @@ static struct device atp_dev = { # define NEXT_DEV (&dev_cops) #endif /* COPS */ +#if defined(CONFIG_IPDDP) + extern int ipddp_init(struct device *dev); + static struct device dev_ipddp = { + "ipddp0\0 ", + 0, 0, 0, 0, + 0x0, 0, + 0, 0, 0, NEXT_DEV, ipddp_init }; +# undef NEXT_DEV +# define NEXT_DEV (&dev_ipddp) +#endif /* CONFIG_IPDDP */ + /* The first device defaults to I/O base '0', which means autoprobe. */ #ifndef ETH0_ADDR # define ETH0_ADDR 0 diff --git a/drivers/net/ipddp.c b/drivers/net/ipddp.c new file mode 100644 index 000000000..8106ffc2d --- /dev/null +++ b/drivers/net/ipddp.c @@ -0,0 +1,309 @@ +/* + * ipddp.c: IP-over-DDP driver for Linux + * + * Authors: + * - Original code by: Bradford W. Johnson <johns393@maroon.tc.umn.edu> + * - Moved to driver by: Jay Schulist <Jay.Schulist@spacs.k12.wi.us> + * + * Derived from: + * - Almost all code already existed in net/appletalk/ddp.c I just + * moved/reorginized it into a driver file. Original IP-over-DDP code + * was done by Bradford W. Johnson <johns393@maroon.tc.umn.edu> + * - skeleton.c: A network driver outline for linux. + * Written 1993-94 by Donald Becker. + * - dummy.c: A dummy net driver. By Nick Holloway. + * + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + */ + +static const char *version = +"ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n"; + +#include <linux/config.h> +#ifdef MODULE +#include <linux/module.h> +#include <linux/version.h> +#endif + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/fcntl.h> +#include <linux/interrupt.h> +#include <linux/ptrace.h> +#include <linux/ioport.h> +#include <linux/in.h> +#include <linux/malloc.h> +#include <linux/string.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/dma.h> +#include <linux/errno.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/if_arp.h> +#include <linux/atalk.h> +#include <linux/ip.h> +#include <net/route.h> + +#include "ipddp.h" /* Our stuff */ + +/* + * The name of the card. Is used for messages and in the requests for + * io regions, irqs and dma channels + */ + +static const char *cardname = "ipddp"; + +/* Use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */ +#ifndef IPDDP_DEBUG +#define IPDDP_DEBUG 1 +#endif +static unsigned int ipddp_debug = IPDDP_DEBUG; + +/* Index to functions, as function prototypes. */ +static int ipddp_xmit(struct sk_buff *skb, struct device *dev); +static struct net_device_stats *ipddp_get_stats(struct device *dev); +static int ipddp_rebuild_header(struct sk_buff *skb); +static int ipddp_header(struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len); +static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd); + + +static int ipddp_open(struct device *dev) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + return 0; +} + +static int ipddp_close(struct device *dev) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + + return 0; +} + +int ipddp_init(struct device *dev) +{ + static unsigned version_printed = 0; + + if (ipddp_debug && version_printed++ == 0) + printk("%s", version); + + /* Initalize the device structure. */ + dev->hard_start_xmit = ipddp_xmit; + + dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL); + if(!dev->priv) + return -ENOMEM; + memset(dev->priv,0,sizeof(struct enet_statistics)); + + dev->open = ipddp_open; + dev->stop = ipddp_close; + dev->get_stats = ipddp_get_stats; + dev->do_ioctl = ipddp_ioctl; + dev->hard_header = ipddp_header; /* see ip_output.c */ + dev->rebuild_header = ipddp_rebuild_header; + + dev->type = ARPHRD_IPDDP; /* IP over DDP tunnel */ + dev->family = AF_INET; + dev->mtu = 585; + dev->flags |= IFF_NOARP; + + /* + * The worst case header we will need is currently a + * ethernet header (14 bytes) and a ddp header (sizeof ddpehdr+1) + * We send over SNAP so that takes another 8 bytes. + */ + dev->hard_header_len = 14+8+sizeof(struct ddpehdr)+1; + + /* Fill in the device structure with ethernet-generic values. */ + ether_setup(dev); + + return 0; +} + +/* + * Transmit LLAP/ELAP frame using aarp_send_ddp. + */ +static int ipddp_xmit(struct sk_buff *skb, struct device *dev) +{ + /* Retrieve the saved address hint */ + struct at_addr *a=(struct at_addr *)skb->data; + skb_pull(skb,4); + + ((struct net_device_stats *) dev->priv)->tx_packets++; + ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len; + + if(ipddp_debug>1) + printk("ipddp_xmit: Headroom %d\n",skb_headroom(skb)); + + if(aarp_send_ddp(skb->dev,skb,a,NULL) < 0) + dev_kfree_skb(skb,FREE_WRITE); + + return 0; +} + +/* + * Get the current statistics. This may be called with the card open or closed. + */ +static struct net_device_stats *ipddp_get_stats(struct device *dev) +{ + return (struct net_device_stats *)dev->priv; +} + +/* + * Now the packet really wants to go out. + */ +static int ipddp_rebuild_header(struct sk_buff *skb) +{ + u32 paddr = ((struct rtable*)skb->dst)->rt_gateway; + struct ddpehdr *ddp; + struct at_addr at; + struct ipddp_route *rt; + struct at_addr *our_addr; + + /* + * On entry skb->data points to the ddpehdr we reserved earlier. + * skb->h.raw will be the higher level header. + */ + + /* + * We created this earlier. + */ + + ddp = (struct ddpehdr *) (skb->data+4); + + /* find appropriate route */ + + for(rt=ipddp_route_head;rt;rt=rt->next) + { + if(rt->ip == paddr) + break; + } + + if(!rt) { + printk("ipddp unreachable dst %08lx\n",ntohl(paddr)); + return -ENETUNREACH; + } + + our_addr = atalk_find_dev_addr(rt->dev); + + /* fill in ddpehdr */ + ddp->deh_len = skb->len; + ddp->deh_hops = 1; + ddp->deh_pad = 0; + ddp->deh_sum = 0; + ddp->deh_dnet = rt->at.s_net; /* FIXME more hops?? */ + ddp->deh_snet = our_addr->s_net; + ddp->deh_dnode = rt->at.s_node; + ddp->deh_snode = our_addr->s_node; + ddp->deh_dport = 72; + ddp->deh_sport = 72; + + *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ + + /* fix up length field */ + *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); + + /* set skb->dev to appropriate device */ + skb->dev = rt->dev; + + /* skb->raddr = (unsigned long) at */ + at = rt->at; + /* Hide it at the start of the buffer */ + memcpy(skb->data,(void *)&at,sizeof(at)); + skb->arp = 1; /* so the actual device doesn't try to arp it... */ + skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ + + return 0; +} + +static int ipddp_header(struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) +{ + if(ipddp_debug>=2) + printk("%s: ipddp_header\n", cardname); + + /* Push down the header space and the type byte */ + skb_push(skb, sizeof(struct ddpehdr)+1+4); + + return 0; +} + +static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + struct ipddp_route *urt = (struct ipddp_route *)ifr->ifr_data; + + if(!suser()) + return -EPERM; + + /* for now we only have one route at a time */ + + switch(cmd) + { + case SIOCADDIPDDPRT: + if(copy_from_user(&ipddp_route_test,urt,sizeof(struct ipddp_route))) + return -EFAULT; + ipddp_route_test.dev = atrtr_get_dev(&ipddp_route_test.at); + if (dev==NULL) + return -ENETUNREACH; + ipddp_route_test.next = NULL; + printk("%s: Added route through %s\n", + ipddp_route_test.dev->name, cardname); + ipddp_route_head = &ipddp_route_test; + return 0; + + case SIOCFINDIPDDPRT: + if(copy_to_user(urt,&ipddp_route_test,sizeof(struct ipddp_route))) + return -EFAULT; + return 0; + + case SIOCDELIPDDPRT: + ipddp_route_test.dev = NULL; + ipddp_route_head = NULL; + return 0; + + default: + return -EINVAL; + } +} + +#ifdef MODULE /* Module specific functions for ipddp.c */ + +static struct device dev_ipddp= +{ + "ipddp0\0 ", + 0, 0, 0, 0, + 0x0, 0, + 0, 0, 0, NULL, ipddp_init +}; + +int init_module(void) +{ + if (register_netdev(&dev_ipddp) != 0) + return -EIO; + + return 0; +} + +void cleanup_module(void) +{ + unregister_netdev(&dev_ipddp); + kfree(dev_ipddp.priv); + dev_ipddp.priv = NULL; +} + +#endif /* MODULE */ diff --git a/drivers/net/ipddp.h b/drivers/net/ipddp.h new file mode 100644 index 000000000..6093adfec --- /dev/null +++ b/drivers/net/ipddp.h @@ -0,0 +1,27 @@ +/* + * ipddp.h: Header for IP-over-DDP driver for Linux. + */ + +#ifndef __LINUX_IPDDP_H +#define __LINUX_IPDDP_H + +#ifdef __KERNEL__ + +#define SIOCADDIPDDPRT SIOCDEVPRIVATE +#define SIOCDELIPDDPRT SIOCDEVPRIVATE+1 +#define SIOCFINDIPDDPRT SIOCDEVPRIVATE+2 + +struct ipddp_route +{ + struct device *dev; /* Carrier device */ + __u32 ip; /* IP address */ + struct at_addr at; /* Gateway appletalk address */ + int flags; + struct ipddp_route *next; +}; + +static struct ipddp_route *ipddp_route_head; +static struct ipddp_route ipddp_route_test; + +#endif /* __KERNEL__ */ +#endif /* __LINUX_IPDDP_H */ diff --git a/drivers/net/x25_asy.c b/drivers/net/x25_asy.c index f6f953201..ce4aeb609 100644 --- a/drivers/net/x25_asy.c +++ b/drivers/net/x25_asy.c @@ -4,6 +4,11 @@ * o tbusy handling * o allow users to set the parameters * o sync/async switching ? + * + * Note: This does _not_ implement CCITT X.25 asynchronous framing + * recommendations. Its primarily for testing purposes. If you wanted + * to do CCITT then in theory all you need is to nick the HDLC async + * checksum routines from ppp.c */ #include <linux/config.h> diff --git a/drivers/pnp/parport_probe.c b/drivers/pnp/parport_probe.c index 85f89e4c7..fc2f82702 100644 --- a/drivers/pnp/parport_probe.c +++ b/drivers/pnp/parport_probe.c @@ -1,4 +1,4 @@ -/* $Id: parport_probe.c,v 1.3 1997/08/06 19:15:53 miguel Exp $ +/* $Id: parport_probe.c,v 1.4 1997/09/12 01:32:20 ralf Exp $ * Parallel port device probing code * * Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de @@ -84,13 +84,13 @@ static long read_polled(struct parport *port, char *buf, return count; } -static struct wait_queue *wait_q = NULL; +static struct wait_queue *wait_q; static void wakeup(void *ref) { struct pardevice **dev = (struct pardevice **)ref; - if (!wait_q || parport_claim(*dev)) + if (!waitqueue_active || parport_claim(*dev)) return; wake_up(&wait_q); @@ -108,10 +108,9 @@ int parport_probe(struct parport *port, char *buffer, int len) return -EINVAL; } - if (parport_claim(dev)) { + init_waitqueue (&wait_q); + if (parport_claim(dev)) sleep_on(&wait_q); - wait_q = NULL; - } switch (parport_ieee1284_nibble_mode_ok(port, 4)) { case 1: diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in index a137680cb..de7a65d6c 100644 --- a/drivers/scsi/Config.in +++ b/drivers/scsi/Config.in @@ -45,7 +45,7 @@ dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $ dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI if [ "$CONFIG_SCSI_EATA" != "n" ]; then bool ' enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE - bool ' enable linked commands' CONFIG_SCSI_EATA_LINKED_COMMANDS + bool ' enable elevator sorting' CONFIG_SCSI_EATA_LINKED_COMMANDS int ' maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16 fi dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI @@ -103,7 +103,7 @@ fi dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then - bool ' enable linked commands' CONFIG_SCSI_U14_34F_LINKED_COMMANDS + bool ' enable elevator sorting' CONFIG_SCSI_U14_34F_LINKED_COMMANDS int ' maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8 fi dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index cfff8bfa3..aeda681c1 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1,5 +1,14 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. + * + * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 + * Use of udelay inside the wait loops to avoid timeout + * problems with fast cpus. + * Removed check about useless calls to the interrupt service + * routine (reported on SMP systems only). + * At initialization time "sorted/unsorted" is displayed instead + * of "linked/unlinked" to reinforce the fact that "linking" is + * nothing but "elevator sorting" in the actual implementation. * * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 * Use of serial_number_at_timeout in abort and reset processing. @@ -283,6 +292,7 @@ MODULE_AUTHOR("Dario Ballabio"); #include <linux/sched.h> #include <linux/kernel.h> #include <linux/ioport.h> +#include <linux/delay.h> #include <asm/io.h> #include <asm/system.h> #include <asm/byteorder.h> @@ -323,6 +333,7 @@ struct proc_dir_entry proc_scsi_eata2x = { #undef DEBUG_INTERRUPT #undef DEBUG_STATISTICS #undef DEBUG_RESET +#undef DEBUG_SMP #define MAX_ISA 4 #define MAX_VESA 0 @@ -351,7 +362,7 @@ struct proc_dir_entry proc_scsi_eata2x = { #define READY 5 #define ABORTING 6 #define NO_DMA 0xff -#define MAXLOOP 200000 +#define MAXLOOP 10000 #define TAG_MIXED 0 #define TAG_SIMPLE 1 #define TAG_HEAD 2 @@ -630,9 +641,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { if (TLDEV(dev->type)) { if (linked_comm && dev->queue_depth > 2) - link_suffix = ", linked"; + link_suffix = ", sorted"; else - link_suffix = ", unlinked"; + link_suffix = ", unsorted"; } if (tagged_comm && dev->tagged_supported && TLDEV(dev->type)) { @@ -656,8 +667,10 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { - while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) + while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { + udelay(1L); if (--loop == 0) return TRUE; + } return FALSE; } @@ -683,8 +696,10 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) { for (p = start; p <= end; p++) { - while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) + while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) { + udelay(1L); if (--loop == 0) return TRUE; + } loop = MAXLOOP; *p = inw(iobase); @@ -1416,7 +1431,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { HD(j)->in_reset = TRUE; sti(); time = jiffies; - while ((jiffies - time) < HZ && limit++ < 100000000); + while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); cli(); printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); @@ -1831,9 +1846,11 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, calls[irq]++; +#if defined (DEBUG_SMP) if (total_loops == 0) printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", driver_name, irq, calls[irq]); +#endif if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", driver_name, irq, calls[irq]); diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h new file mode 100644 index 000000000..8292ef514 --- /dev/null +++ b/drivers/scsi/eata.h @@ -0,0 +1,41 @@ +/* + * eata.h - used by the low-level driver for EATA/DMA SCSI host adapters. + */ +#ifndef _EATA_H +#define _EATA_H + +#include <scsi/scsicam.h> + +int eata2x_detect(Scsi_Host_Template *); +int eata2x_release(struct Scsi_Host *); +int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int eata2x_abort(Scsi_Cmnd *); +int eata2x_reset(Scsi_Cmnd *, unsigned int); + +#define EATA_VERSION "3.11.00" + + +#define EATA { \ + NULL, /* Ptr for modules */ \ + NULL, /* usage count for modules */ \ + NULL, \ + NULL, \ + "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ + eata2x_detect, \ + eata2x_release, \ + NULL, \ + NULL, \ + eata2x_queuecommand, \ + eata2x_abort, \ + eata2x_reset, \ + NULL, \ + scsicam_bios_param, \ + 0, /* can_queue, reset by detect */ \ + 7, /* this_id, reset by detect */ \ + 0, /* sg_tablesize, reset by detect */ \ + 0, /* cmd_per_lun, reset by detect */ \ + 0, /* number of boards present */ \ + 1, /* unchecked isa dma, reset by detect */ \ + ENABLE_CLUSTERING \ + } +#endif diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index a81e77d7a..e8f73f1b2 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -18,12 +18,14 @@ * Some XA-Sector tweaking, required for older drives. * * - SONY: Detection and support of multisession CD's. - * added by Thomas Quinot <operator@melchior.cuivre.fdn.fr> + * added by Thomas Quinot <thomas@cuivre.freenix.fr> * - * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC: known to work with SONY code. + * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS: + * Known to work with SONY code. * * - HP: Much like SONY, but a little different... (Thomas) * HP-Writers only ??? Maybe other CD-Writers work with this too ? + * HP 6020 writers now supported. */ #include <linux/errno.h> @@ -44,7 +46,10 @@ #define VENDOR_NEC 2 #define VENDOR_TOSHIBA 3 #define VENDOR_SONY_LIKE 4 /* much drives are Sony compatible */ -#define VENDOR_HP 5 /* HP Writers, others too ?? */ +#define VENDOR_HP_4020 5 /* HP 4xxx writers, others too ?? */ +#define VENDOR_HP_6020 6 /* HP 6020 writers */ + +#define VENDOR_ID (scsi_CDs[minor].vendor) #if 0 #define DEBUG @@ -58,10 +63,13 @@ sr_vendor_init(int minor) if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) && scsi_CDs[minor].device->type == TYPE_WORM) { - scsi_CDs[minor].vendor = VENDOR_HP; + if (!strncmp(model,"CD-Writer 6020",14)) + VENDOR_ID = VENDOR_HP_6020; + else + VENDOR_ID = VENDOR_HP_4020; } else if (!strncmp (vendor, "NEC", 3)) { - scsi_CDs[minor].vendor = VENDOR_NEC; + VENDOR_ID = VENDOR_NEC; if (!strncmp (model,"CD-ROM DRIVE:25", 15) || !strncmp (model,"CD-ROM DRIVE:36", 15) || !strncmp (model,"CD-ROM DRIVE:83", 15) || @@ -70,12 +78,12 @@ sr_vendor_init(int minor) scsi_CDs[minor].cdi.mask |= CDC_MULTI_SESSION; } else if (!strncmp (vendor, "TOSHIBA", 7)) { - scsi_CDs[minor].vendor = VENDOR_TOSHIBA; + VENDOR_ID = VENDOR_TOSHIBA; } else { - /* most drives can handled like sony ones, so we take + /* most drives can handled like Sony ones, so we take * it as default */ - scsi_CDs[minor].vendor = VENDOR_SONY_LIKE; + VENDOR_ID = VENDOR_SONY_LIKE; #ifdef DEBUG printk(KERN_DEBUG "sr: using \"Sony group\" multisession code\n"); @@ -128,7 +136,7 @@ sr_read_sector(int minor, int lba, int blksize, unsigned char *dest) unsigned char cmd[12]; /* the scsi-command */ int rc, density; - density = (scsi_CDs[minor].vendor == VENDOR_TOSHIBA) ? 0x83 : 0; + density = (VENDOR_ID == VENDOR_TOSHIBA) ? 0x83 : 0; buffer = (unsigned char *) scsi_malloc(512); if (!buffer) return -ENOMEM; @@ -177,7 +185,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) no_multi = 0; /* flag: the drive can't handle multisession */ rc = 0; - switch(scsi_CDs[minor].vendor) { + switch(VENDOR_ID) { case VENDOR_NEC: memset(cmd,0,12); @@ -222,12 +230,16 @@ int sr_cd_check(struct cdrom_device_info *cdi) sector -= CD_BLOCK_OFFSET; break; - case VENDOR_HP: + case VENDOR_HP_4020: + /* Fallthrough */ + case VENDOR_HP_6020: cmd[0] = READ_TOC; cmd[1] = (scsi_CDs[minor].device->lun << 5); - cmd[8] = 0x04; + cmd[8] = (VENDOR_ID == VENDOR_HP_4020) ? + 0x04 : 0x0c; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12); + rc = sr_do_ioctl(minor, cmd, buffer, + (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c); if (rc != 0) { break; } @@ -237,31 +249,23 @@ int sr_cd_check(struct cdrom_device_info *cdi) break; } - cmd[0] = READ_TOC; /* Read TOC */ - cmd[1] = (scsi_CDs[minor].device->lun << 5); - cmd[6] = rc & 0x7f; /* number of last session */ - cmd[8] = 0x0c; - cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12); - if (rc != 0) { - break; + if (VENDOR_ID == VENDOR_HP_4020) { + cmd[0] = READ_TOC; /* Read TOC */ + cmd[1] = (scsi_CDs[minor].device->lun << 5); + cmd[6] = rc & 0x7f; /* number of last session */ + cmd[8] = 0x0c; + cmd[9] = 0x40; + rc = sr_do_ioctl(minor, cmd, buffer, 12); + if (rc != 0) { + break; + } } -#undef STRICT_HP -#ifdef STRICT_HP - sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16); - /* HP documentation states that Logical Start Address is - returned as three (!) bytes, and that buffer[8] is - reserved. This is strange, because a LBA usually is - 4 bytes long. */ -#else sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16) + (buffer[8] << 24); -#endif break; case VENDOR_SONY_LIKE: - /* Thomas QUINOT <thomas@melchior.cuivre.fdn.fr> */ memset(cmd,0,12); cmd[0] = READ_TOC; cmd[1] = (scsi_CDs[minor].device->lun << 5); @@ -293,7 +297,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) /* should not happen */ printk(KERN_WARNING "sr: unknown vendor code (%i), not initialized ?\n", - scsi_CDs[minor].vendor); + VENDOR_ID); sector = 0; no_multi = 1; break; diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 6a0076dde..fa980051a 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1,6 +1,15 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 + * Use of udelay inside the wait loops to avoid timeout + * problems with fast cpus. + * Removed check about useless calls to the interrupt service + * routine (reported on SMP systems only). + * At initialization time "sorted/unsorted" is displayed instead + * of "linked/unlinked" to reinforce the fact that "linking" is + * nothing but "elevator sorting" in the actual implementation. + * * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 * Use of serial_number_at_timeout in abort and reset processing. * Use of the __initfunc and __initdata macro in setup code. @@ -269,6 +278,7 @@ MODULE_AUTHOR("Dario Ballabio"); #include <linux/sched.h> #include <linux/kernel.h> #include <linux/ioport.h> +#include <linux/delay.h> #include <asm/io.h> #include <asm/system.h> #include <asm/byteorder.h> @@ -321,6 +331,7 @@ struct proc_dir_entry proc_scsi_u14_34f = { #undef DEBUG_INTERRUPT #undef DEBUG_STATISTICS #undef DEBUG_RESET +#undef DEBUG_SMP #define MAX_ISA 3 #define MAX_VESA 1 @@ -349,7 +360,7 @@ struct proc_dir_entry proc_scsi_u14_34f = { #define READY 5 #define ABORTING 6 #define NO_DMA 0xff -#define MAXLOOP 200000 +#define MAXLOOP 10000 #define REG_LCL_MASK 0 #define REG_LCL_INTR 1 @@ -530,9 +541,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { if (TLDEV(dev->type)) { if (linked_comm && dev->queue_depth > 2) - link_suffix = ", linked"; + link_suffix = ", sorted"; else - link_suffix = ", unlinked"; + link_suffix = ", unsorted"; } if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue) @@ -551,8 +562,10 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { - while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) + while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) { + udelay(1L); if (--loop == 0) return TRUE; + } return FALSE; } @@ -588,7 +601,7 @@ static int board_inquiry(unsigned int j) { sti(); time = jiffies; - while ((jiffies - time) < HZ && limit++ < 100000000); + while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L); cli(); if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) { @@ -1195,7 +1208,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { HD(j)->in_reset = TRUE; sti(); time = jiffies; - while ((jiffies - time) < HZ && limit++ < 100000000); + while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); cli(); printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); @@ -1616,9 +1629,11 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, calls[irq]++; +#if defined (DEBUG_SMP) if (total_loops == 0) printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", driver_name, irq, calls[irq]); +#endif if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", driver_name, irq, calls[irq]); diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h index 9381f7729..004936393 100644 --- a/drivers/scsi/u14-34f.h +++ b/drivers/scsi/u14-34f.h @@ -11,7 +11,7 @@ int u14_34f_abort(Scsi_Cmnd *); int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "3.10.00" +#define U14_34F_VERSION "3.11.00" #define ULTRASTOR_14_34F { \ NULL, /* Ptr for modules */ \ diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index b7da7932a..1c37f9f5a 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -668,10 +668,9 @@ static long state_read(char *dest, unsigned long count); static int sound_open(struct inode *inode, struct file *file); -static int sound_fsync(struct inode *inode, struct file *filp); +static int sound_fsync(struct file *filp, struct dentry *dentry); static void sound_release(struct inode *inode, struct file *file); -static long long sound_lseek(struct inode *inode, struct file *file, - long long offset, int orig); +static long long sound_lseek(struct file *file, long long offset, int orig); static long sound_read(struct inode *inode, struct file *file, char *buf, unsigned long count); static long sound_write(struct inode *inode, struct file *file, @@ -3071,9 +3070,9 @@ static int sound_open(struct inode *inode, struct file *file) } -static int sound_fsync(struct inode *inode, struct file *filp) +static int sound_fsync(struct file *filp, struct dentry *dentry) { - int dev = MINOR(inode->i_rdev) & 0x0f; + int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f; switch (dev) { case SND_DEV_STATUS: @@ -3116,8 +3115,7 @@ static void sound_release(struct inode *inode, struct file *file) } -static long long sound_lseek(struct inode *inode, struct file *file, - long long offset, int orig) +static long long sound_lseek(struct file *file, long long offset, int orig) { return -ESPIPE; } @@ -3186,25 +3184,25 @@ static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, return(0); case SNDCTL_DSP_POST: case SNDCTL_DSP_SYNC: - return(sound_fsync(inode, file)); + return(sound_fsync(file, file->f_dentry)); /* ++TeSche: before changing any of these it's probably wise to * wait until sound playing has settled down */ case SNDCTL_DSP_SPEED: - sound_fsync(inode, file); + sound_fsync(file, file->f_dentry); IOCTL_IN(arg, data); return(IOCTL_OUT(arg, sound_set_speed(data))); case SNDCTL_DSP_STEREO: - sound_fsync(inode, file); + sound_fsync(file, file->f_dentry); IOCTL_IN(arg, data); return(IOCTL_OUT(arg, sound_set_stereo(data))); case SOUND_PCM_WRITE_CHANNELS: - sound_fsync(inode, file); + sound_fsync(file, file->f_dentry); IOCTL_IN(arg, data); return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1)); case SNDCTL_DSP_SETFMT: - sound_fsync(inode, file); + sound_fsync(file, file->f_dentry); IOCTL_IN(arg, data); return(IOCTL_OUT(arg, sound_set_format(data))); case SNDCTL_DSP_GETFMTS: diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index a9af5956b..450197a34 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -80,8 +80,7 @@ sound_write (struct inode *inode, struct file *file, const char *buf, unsigned l return sound_write_sw (dev, &files[dev], buf, count); } -static long long -sound_lseek (struct inode *inode, struct file *file, long long offset, int orig) +static long long sound_lseek (struct file *file, long long offset, int orig) { return -EPERM; } @@ -139,8 +138,8 @@ sound_release (struct inode *inode, struct file *file) sound_release_sw (dev, &files[dev]); #ifdef MODULE MOD_DEC_USE_COUNT; - return 0; #endif + return 0; } static int @@ -256,13 +255,13 @@ sound_poll (struct file *file, poll_table * wait) } static int -sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) +sound_mmap (struct file *file, struct vm_area_struct *vma) { int dev, dev_class; unsigned long size; struct dma_buffparms *dmap = NULL; - dev = MINOR (inode->i_rdev); + dev = MINOR (file->f_dentry->d_inode->i_rdev); files[dev].flags = file->f_flags; |