diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-27 23:54:12 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-27 23:54:12 +0000 |
commit | d3e71cb08747743fce908122bab08b479eb403a5 (patch) | |
tree | cbec6948fdbdee9af81cf3ecfb504070d2745d7b /drivers/char | |
parent | fe7ff1706e323d0e5ed83972960a1ecc1ee538b3 (diff) |
Merge with Linux 2.3.99-pre3.
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/acquirewdt.c | 10 | ||||
-rw-r--r-- | drivers/char/amigamouse.c | 6 | ||||
-rw-r--r-- | drivers/char/amiserial.c | 2 | ||||
-rw-r--r-- | drivers/char/applicom.c | 1167 | ||||
-rw-r--r-- | drivers/char/atixlmouse.c | 22 | ||||
-rw-r--r-- | drivers/char/bttv.c | 206 | ||||
-rw-r--r-- | drivers/char/bttv.h | 11 | ||||
-rw-r--r-- | drivers/char/busmouse.c | 126 | ||||
-rw-r--r-- | drivers/char/busmouse.h | 2 | ||||
-rw-r--r-- | drivers/char/misc.c | 34 | ||||
-rw-r--r-- | drivers/char/rtc.c | 10 | ||||
-rw-r--r-- | drivers/char/serial.c | 290 | ||||
-rw-r--r-- | drivers/char/sysrq.c | 36 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 3 | ||||
-rw-r--r-- | drivers/char/wdt.c | 6 |
15 files changed, 1023 insertions, 908 deletions
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c index 2a8da5960..9d86479dc 100644 --- a/drivers/char/acquirewdt.c +++ b/drivers/char/acquirewdt.c @@ -37,8 +37,10 @@ #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <linux/spinlock.h> static int acq_is_open=0; +static spinlock_t acq_lock; /* * You must set these - there is no sane way to probe for this board. @@ -117,8 +119,12 @@ static int acq_open(struct inode *inode, struct file *file) switch(MINOR(inode->i_rdev)) { case WATCHDOG_MINOR: + spin_lock(&acq_lock); if(acq_is_open) + { + spin_unlock(&acq_lock); return -EBUSY; + } MOD_INC_USE_COUNT; /* * Activate @@ -126,6 +132,7 @@ static int acq_open(struct inode *inode, struct file *file) acq_is_open=1; inb_p(WDT_START); + spin_unlock(&acq_lock); return 0; default: return -ENODEV; @@ -136,10 +143,12 @@ static int acq_close(struct inode *inode, struct file *file) { if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) { + spin_lock(&acq_lock); #ifndef CONFIG_WATCHDOG_NOWAYOUT inb_p(WDT_STOP); #endif acq_is_open=0; + spin_unlock(&acq_lock); } MOD_DEC_USE_COUNT; return 0; @@ -211,6 +220,7 @@ int __init acq_init(void) { printk("WDT driver for Acquire single board computer initialising.\n"); + spin_lock_init(&acq_lock); misc_register(&acq_miscdev); request_region(WDT_STOP, 1, "Acquire WDT"); request_region(WDT_START, 1, "Acquire WDT"); diff --git a/drivers/char/amigamouse.c b/drivers/char/amigamouse.c index 823ec88ea..0cdfc264a 100644 --- a/drivers/char/amigamouse.c +++ b/drivers/char/amigamouse.c @@ -162,6 +162,10 @@ static int release_mouse(struct inode * inode, struct file * file) static int open_mouse(struct inode * inode, struct file * file) { + /* Lock module first - request_irq might sleep */ + + MOD_INC_USE_COUNT; + /* * use VBL to poll mouse deltas */ @@ -169,10 +173,10 @@ static int open_mouse(struct inode * inode, struct file * file) if(request_irq(IRQ_AMIGA_VERTB, mouse_interrupt, 0, "Amiga mouse", mouse_interrupt)) { printk(KERN_INFO "Installing Amiga mouse failed.\n"); + MOD_DEC_USE_COUNT; return -EIO; } - MOD_INC_USE_COUNT; #if AMIGA_OLD_INT AMI_MSE_INT_ON(); #endif diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 969a75331..7ede5fdc6 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -2259,6 +2259,6 @@ void cleanup_module(void) /* Local variables: - compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -DCPU=686 -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c amiserial.c" + compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c amiserial.c" End: */ diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index f6304943a..65be2102f 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -14,7 +14,7 @@ /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */ /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */ /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */ -/* adresses de base des cartes, IOCTL 6 plus complet */ +/* adresses de base des cartes, IOCTL 6 plus complet */ /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */ /* de code autre que le texte V2.6.1 en V2.8.0 */ /*****************************************************************************/ @@ -37,108 +37,102 @@ #undef DEBUG #define DEVPRIO PZERO+8 #define FALSE 0 -#define TRUE ~FALSE -#define MAX_BOARD 8 /* maximum of pc board possible */ +#define TRUE ~FALSE +#define MAX_BOARD 8 /* maximum of pc board possible */ #define MAX_ISA_BOARD 4 #define LEN_RAM_IO 0x800 #define AC_MINOR 157 #ifndef PCI_VENDOR_ID_APPLICOM -#define PCI_VENDOR_ID_APPLICOM 0x1389 +#define PCI_VENDOR_ID_APPLICOM 0x1389 #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001 #define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 #define MAX_PCI_DEVICE_NUM 3 #endif -static char *applicom_pci_devnames[]={ - "PCI board", "PCI2000IBS / PCI2000CAN", "PCI2000PFB"}; +static char *applicom_pci_devnames[] = { + "PCI board", "PCI2000IBS / PCI2000CAN", "PCI2000PFB" +}; MODULE_AUTHOR("David Woodhouse & Applicom International"); MODULE_DESCRIPTION("Driver for Applicom Profibus card"); MODULE_PARM(irq, "i"); MODULE_PARM_DESC(irq, "IRQ of the Applicom board"); -MODULE_PARM(mem,"i"); +MODULE_PARM(mem, "i"); MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board"); MODULE_SUPPORTED_DEVICE("ac"); struct applicom_board { - unsigned long PhysIO; - unsigned long RamIO; + unsigned long PhysIO; + unsigned long RamIO; #if LINUX_VERSION_CODE > 0x20300 - wait_queue_head_t FlagSleepSend; + wait_queue_head_t FlagSleepSend; #else - struct wait_queue *FlagSleepSend; + struct wait_queue *FlagSleepSend; #endif - long irq; + long irq; } apbs[MAX_BOARD]; -static unsigned int irq=0; /* interrupt number IRQ */ -static unsigned long mem=0; /* physical segment of board */ +static unsigned int irq = 0; /* interrupt number IRQ */ +static unsigned long mem = 0; /* physical segment of board */ -static unsigned int numboards; /* number of installed boards */ +static unsigned int numboards; /* number of installed boards */ static volatile unsigned char Dummy; #if LINUX_VERSION_CODE > 0x20300 -static DECLARE_WAIT_QUEUE_HEAD (FlagSleepRec); +static DECLARE_WAIT_QUEUE_HEAD(FlagSleepRec); #else static struct wait_queue *FlagSleepRec; #endif -static unsigned int WriteErrorCount; /* number of write error */ -static unsigned int ReadErrorCount; /* number of read error */ -static unsigned int DeviceErrorCount; /* number of device error */ +static unsigned int WriteErrorCount; /* number of write error */ +static unsigned int ReadErrorCount; /* number of read error */ +static unsigned int DeviceErrorCount; /* number of device error */ static loff_t ac_llseek(struct file *file, loff_t offset, int origin); static int ac_open(struct inode *inode, struct file *filp); -static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr); -static ssize_t ac_write (struct file *file, const char *buf, size_t count, loff_t *ppos); +static ssize_t ac_read(struct file *filp, char *buf, size_t count, loff_t * ptr); +static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos); static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); static int ac_release(struct inode *inode, struct file *file); static void ac_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -struct file_operations ac_fops={ - llseek: ac_llseek, - read: ac_read, - write: ac_write, - ioctl: ac_ioctl, - open: ac_open, - release: ac_release, +struct file_operations ac_fops = { + llseek:ac_llseek, + read:ac_read, + write:ac_write, + ioctl:ac_ioctl, + open:ac_open, + release:ac_release, }; -struct miscdevice ac_miscdev={ - AC_MINOR, - "ac", - &ac_fops +struct miscdevice ac_miscdev = { + AC_MINOR, + "ac", + &ac_fops }; -int ac_register_board(unsigned long physloc, unsigned long loc, - unsigned char boardno) +int ac_register_board(unsigned long physloc, unsigned long loc, unsigned char boardno) { volatile unsigned char byte_reset_it; - if((readb(loc + CONF_END_TEST) != 0x00) || - (readb(loc + CONF_END_TEST + 1) != 0x55) || - (readb(loc + CONF_END_TEST + 2) != 0xAA) || - (readb(loc + CONF_END_TEST + 3) != 0xFF)) - return 0; + if ((readb(loc + CONF_END_TEST) != 0x00) || (readb(loc + CONF_END_TEST + 1) != 0x55) || (readb(loc + CONF_END_TEST + 2) != 0xAA) || (readb(loc + CONF_END_TEST + 3) != 0xFF)) + return 0; if (!boardno) - boardno = readb(loc + NUMCARD_OWNER_TO_PC); + boardno = readb(loc + NUMCARD_OWNER_TO_PC); - if (!boardno && boardno > MAX_BOARD) - { - printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",boardno, physloc, MAX_BOARD); - return 0; - } + if (!boardno && boardno > MAX_BOARD) { + printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", boardno, physloc, MAX_BOARD); + return 0; + } - if (apbs[boardno-1].RamIO) - { - printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", - boardno, physloc, boardno, apbs[boardno-1].PhysIO); - return 0; - } + if (apbs[boardno - 1].RamIO) { + printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", boardno, physloc, boardno, apbs[boardno - 1].PhysIO); + return 0; + } boardno--; @@ -152,7 +146,7 @@ int ac_register_board(unsigned long physloc, unsigned long loc, byte_reset_it = readb(loc + RAM_IT_TO_PC); numboards++; - return boardno+1; + return boardno + 1; } #ifdef MODULE @@ -164,22 +158,21 @@ void cleanup_module(void) int i; misc_deregister(&ac_miscdev); - for (i=0; i< MAX_BOARD; i++) - { - if (!apbs[i].RamIO) - continue; - iounmap((void *)apbs[i].RamIO); - if (apbs[i].irq) - free_irq(apbs[i].irq,&ac_open); - } - // printk("Removing Applicom module\n"); + for (i = 0; i < MAX_BOARD; i++) { + if (!apbs[i].RamIO) + continue; + iounmap((void *) apbs[i].RamIO); + if (apbs[i].irq) + free_irq(apbs[i].irq, &ac_open); + } + // printk("Removing Applicom module\n"); } -#endif /* MODULE */ +#endif /* MODULE */ int __init applicom_init(void) { - int i, numisa=0; + int i, numisa = 0; struct pci_dev *dev = NULL; void *RamIO; int boardno; @@ -190,157 +183,137 @@ int __init applicom_init(void) #endif printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $\n"); - + /* No mem and irq given - check for a PCI card */ - - while ( (dev = pci_find_device(PCI_VENDOR_ID_APPLICOM, 1, dev))) - { - // mem = dev->base_address[0]; - // irq = dev->irq; - - RamIO = ioremap(PCI_BASE_ADDRESS(dev), LEN_RAM_IO); - - if (!RamIO) { - printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", PCI_BASE_ADDRESS(dev)); - return -EIO; - } - - printk(KERN_INFO "Applicom %s found at mem 0x%lx, irq %d\n", - applicom_pci_devnames[dev->device-1], PCI_BASE_ADDRESS(dev), - dev->irq); - - if (!(boardno = ac_register_board(PCI_BASE_ADDRESS(dev), - (unsigned long)RamIO,0))) - { - printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); - iounmap(RamIO); - continue; - } - - if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &ac_open)) - { - printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq); - iounmap(RamIO); - apbs[boardno-1].RamIO = 0; - continue; - } - - /* Enable interrupts. */ - - writeb(0x40, apbs[boardno-1].RamIO + RAM_IT_FROM_PC); - - apbs[boardno-1].irq = dev->irq; - } - + + while ((dev = pci_find_device(PCI_VENDOR_ID_APPLICOM, 1, dev))) { + // mem = dev->base_address[0]; + // irq = dev->irq; + + RamIO = ioremap(PCI_BASE_ADDRESS(dev), LEN_RAM_IO); + + if (!RamIO) { + printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", PCI_BASE_ADDRESS(dev)); + return -EIO; + } + + printk(KERN_INFO "Applicom %s found at mem 0x%lx, irq %d\n", applicom_pci_devnames[dev->device - 1], PCI_BASE_ADDRESS(dev), dev->irq); + + if (!(boardno = ac_register_board(PCI_BASE_ADDRESS(dev), (unsigned long) RamIO, 0))) { + printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); + iounmap(RamIO); + continue; + } + + if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &ac_open)) { + printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq); + iounmap(RamIO); + apbs[boardno - 1].RamIO = 0; + continue; + } + + /* Enable interrupts. */ + + writeb(0x40, apbs[boardno - 1].RamIO + RAM_IT_FROM_PC); + + apbs[boardno - 1].irq = dev->irq; + } + /* Finished with PCI cards. If none registered, * and there was no mem/irq specified, exit */ - if (!mem || !irq) - { - if (numboards) - goto fin; - else - { - printk(KERN_INFO "ac.o: No PCI boards found.\n"); - printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n"); - return -ENXIO; - } - } - + if (!mem || !irq) { + if (numboards) + goto fin; + else { + printk(KERN_INFO "ac.o: No PCI boards found.\n"); + printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n"); + return -ENXIO; + } + } + /* Now try the specified ISA cards */ - RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); + RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); if (!RamIO) { - printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n",mem); + printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n", mem); + } + + for (i = 0; i < MAX_ISA_BOARD; i++) { + RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO); + + if (!RamIO) { + printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1); + continue; + } + + if (!(boardno = ac_register_board((unsigned long) mem + (LEN_RAM_IO * i), (unsigned long) RamIO, i + 1))) { + iounmap(RamIO); + continue; + } + + printk("Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO * i), irq); + + if (!numisa) { + if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &ac_open)) { + printk("Could not allocate IRQ %d for ISA Applicom device.\n", irq); + iounmap((void *) RamIO); + apbs[boardno - 1].RamIO = 0; + } + apbs[boardno - 1].irq = irq; + } else + apbs[boardno - 1].irq = 0; + + numisa++; } - - for (i=0; i< MAX_ISA_BOARD; i++) - { - RamIO = ioremap(mem+ (LEN_RAM_IO*i), LEN_RAM_IO); - - if (!RamIO) { - printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n",i+1); - continue; - } - - if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i), - (unsigned long)RamIO,i+1))) { - iounmap(RamIO); - continue; - } - - printk("Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq); - - if (!numisa) - { - if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &ac_open)) - { - printk("Could not allocate IRQ %d for ISA Applicom device.\n", irq); - iounmap((void *)RamIO); - apbs[boardno-1].RamIO = 0; - } - apbs[boardno-1].irq=irq; - } - else - apbs[boardno-1].irq=0; - - numisa++; - } if (!numisa) - printk("ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem); + printk("ac.o: No valid ISA Applicom boards found at mem 0x%lx\n", mem); #if LINUX_VERSION_CODE > 0x20300 init_waitqueue_head(&FlagSleepRec); #else - FlagSleepRec = NULL; + FlagSleepRec = NULL; #endif - WriteErrorCount = 0; - ReadErrorCount = 0; + WriteErrorCount = 0; + ReadErrorCount = 0; DeviceErrorCount = 0; -fin: - if (numboards) - { - misc_register (&ac_miscdev); - for (i=0; i<MAX_BOARD; i++) - { - int serial; - char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1]; + fin: + if (numboards) { + misc_register(&ac_miscdev); + for (i = 0; i < MAX_BOARD; i++) { + int serial; + char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1]; - if (!apbs[i].RamIO) - continue; - - for(serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) - boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); - boardname[serial]=0; - + if (!apbs[i].RamIO) + continue; - printk("Applicom board %d: %s, PROM V%d.%d", - i+1, boardname, - (int)(readb(apbs[i].RamIO + VERS) >> 4), - (int)(readb(apbs[i].RamIO + VERS) & 0xF)); + for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) + boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); + boardname[serial] = 0; + + + printk(KERN_INFO "Applicom board %d: %s, PROM V%d.%d", i + 1, boardname, (int) (readb(apbs[i].RamIO + VERS) >> 4), (int) (readb(apbs[i].RamIO + VERS) & 0xF)); + + serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2)); + + if (serial != 0) + printk(" S/N %d\n", serial); + else + printk("\n"); + } + return 0; + } - serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) ); - - if (serial != 0) - printk (" S/N %d\n", serial); - else - printk("\n"); - } - return 0; - } - else - return -ENXIO; + return -ENXIO; } #ifndef MODULE -__initcall (applicom_init); +__initcall(applicom_init); #endif static loff_t ac_llseek(struct file *file, loff_t offset, int origin) @@ -361,477 +334,455 @@ static int ac_release(struct inode *inode, struct file *file) } -static ssize_t ac_write (struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { - unsigned int NumCard; /* Board number 1 -> 8 */ - unsigned int IndexCard; /* Index board number 0 -> 7 */ - unsigned char TicCard; /* Board TIC to send */ - unsigned long flags; /* Current priority */ - struct st_ram_io st_loc; - struct mailbox tmpmailbox; - - if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - printk("Hmmm. write() of Applicom card, length %d != expected %d\n",count,sizeof(struct st_ram_io) + sizeof(struct mailbox)); - return -EINVAL; - } - - if(copy_from_user (&st_loc, buf, sizeof(struct st_ram_io))) { - return -EFAULT; - } - if(copy_from_user (&tmpmailbox, &buf[sizeof(struct st_ram_io)], sizeof(struct mailbox))) { - return -EFAULT; - } - - NumCard = st_loc.num_card; /* board number to send */ - TicCard = st_loc.tic_des_from_pc; /* tic number to send */ - IndexCard = NumCard -1; - if((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO) - { /* User board number not OK */ - // printk("Write to invalid Applicom board %d\n", NumCard); - return -EINVAL; /* Return error code user buffer */ - } - + unsigned int NumCard; /* Board number 1 -> 8 */ + unsigned int IndexCard; /* Index board number 0 -> 7 */ + unsigned char TicCard; /* Board TIC to send */ + unsigned long flags; /* Current priority */ + struct st_ram_io st_loc; + struct mailbox tmpmailbox; + + if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { + printk("Hmmm. write() of Applicom card, length %d != expected %d\n", count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); + return -EINVAL; + } + + if (copy_from_user(&st_loc, buf, sizeof(struct st_ram_io))) { + return -EFAULT; + } + if (copy_from_user(&tmpmailbox, &buf[sizeof(struct st_ram_io)], sizeof(struct mailbox))) { + return -EFAULT; + } + + NumCard = st_loc.num_card; /* board number to send */ + TicCard = st_loc.tic_des_from_pc; /* tic number to send */ + IndexCard = NumCard - 1; + if ((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO) { /* User board number not OK */ + // printk("Write to invalid Applicom board %d\n", NumCard); + return -EINVAL; /* Return error code user buffer */ + } #ifdef DEBUG - { - int c; - - printk("Write to applicom card #%d. struct st_ram_io follows:",NumCard); - - - - for (c=0; c< sizeof(struct st_ram_io);) - { - printk("\n%5.5X: %2.2X",c,((unsigned char *)&st_loc)[c]); - - for (c++ ; c%8 && c<sizeof(struct st_ram_io); c++) - { - printk(" %2.2X",((unsigned char *)&st_loc)[c]); - } - } + { + int c; + + printk("Write to applicom card #%d. struct st_ram_io follows:", NumCard); + + + + for (c = 0; c < sizeof(struct st_ram_io);) { + printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]); + + for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) { + printk(" %2.2X", ((unsigned char *) &st_loc)[c]); + } + } + + printk("\nstruct mailbox follows:"); + + for (c = 0; c < sizeof(struct mailbox);) { + printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]); + + for (c++; c % 8 && c < sizeof(struct mailbox); c++) { + printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]); + } + } + + printk("\n"); + } - printk("\nstruct mailbox follows:"); - - for (c=0; c< sizeof(struct mailbox);) - { - printk("\n%5.5X: %2.2X",c,((unsigned char *)&tmpmailbox)[c]); - - for (c++ ; c%8 && c<sizeof(struct mailbox); c++) - { - printk(" %2.2X",((unsigned char *)&tmpmailbox)[c]); - } - } - - printk("\n"); - } - #endif - save_flags (flags); - cli(); /* disable interrupt */ - - if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) /* Test octet ready correct */ - { - Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); - printk("APPLICOM driver write error board %d, DataFromPcReady = %d\n", - IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY)); - DeviceErrorCount++; - return -EIO; - } - while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0) - { - Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); - interruptible_sleep_on (&apbs[IndexCard].FlagSleepSend); - if (signal_pending(current)) - return -EINTR; - save_flags(flags); - cli(); - } - writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - - // memcpy_toio ((void *)apbs[IndexCard].PtrRamFromPc, (void *)&tmpmailbox, sizeof(struct mailbox)); - { - unsigned char *from = (unsigned char *)&tmpmailbox; - unsigned long to = (unsigned long)apbs[IndexCard].RamIO + RAM_FROM_PC; - int c; - - for (c=0; c<sizeof(struct mailbox) ; c++) - writeb(*(from++), to++); - } - writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC); - writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC); - writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC); - writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); - writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags (flags); - return 0; + save_flags(flags); + cli(); /* disable interrupt */ + + if (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) { /* Test octet ready correct */ + Dummy = readb(apbs[IndexCard].RamIO + VERS); + restore_flags(flags); + printk("APPLICOM driver write error board %d, DataFromPcReady = %d\n", IndexCard, (int) readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY)); + DeviceErrorCount++; + return -EIO; + } + while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0) { + Dummy = readb(apbs[IndexCard].RamIO + VERS); + restore_flags(flags); + /* + * FIXME: Race on wakeup. Race on re-entering write + * in another thread. + */ + interruptible_sleep_on(&apbs[IndexCard].FlagSleepSend); + if (signal_pending(current)) + return -EINTR; + save_flags(flags); + cli(); + } + writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); + + // memcpy_toio ((void *)apbs[IndexCard].PtrRamFromPc, (void *)&tmpmailbox, sizeof(struct mailbox)); + { + unsigned char *from = (unsigned char *) &tmpmailbox; + unsigned long to = (unsigned long) apbs[IndexCard].RamIO + RAM_FROM_PC; + int c; + + for (c = 0; c < sizeof(struct mailbox); c++) + writeb(*(from++), to++); + } + writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC); + writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC); + writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC); + writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); + writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); + writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); + Dummy = readb(apbs[IndexCard].RamIO + VERS); + restore_flags(flags); + return 0; } -static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr) +static ssize_t ac_read(struct file *filp, char *buf, size_t count, loff_t * ptr) { - unsigned int NumCard; /* board number 1 -> 8 */ - unsigned int IndexCard; /* index board number 0 -> 7 */ - unsigned long flags; - unsigned int i; - unsigned char tmp=0; - struct st_ram_io st_loc; - struct mailbox tmpmailbox; /* bounce buffer - can't copy to user space with cli() */ - - - if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - printk("Hmmm. read() of Applicom card, length %d != expected %d\n",count,sizeof(struct st_ram_io) + sizeof(struct mailbox)); - return -EINVAL; - } - - save_flags(flags); - cli(); - - i = 0; - - while (tmp != 2) - { - for (i=0; i < MAX_BOARD; i++) - { - if (!apbs[i].RamIO) - continue; - - tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY); - - if (tmp == 2) - break; - - if (tmp > 2) /* Test octet ready correct */ - { - Dummy = readb(apbs[i].RamIO + VERS); - restore_flags(flags); - printk("APPLICOM driver read error board %d, DataToPcReady = %d\n", - i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY)); - DeviceErrorCount++; - return -EIO; - } - Dummy = readb(apbs[i].RamIO + VERS); + unsigned int NumCard; /* board number 1 -> 8 */ + unsigned int IndexCard; /* index board number 0 -> 7 */ + unsigned long flags; + unsigned int i; + unsigned char tmp = 0; + struct st_ram_io st_loc; + struct mailbox tmpmailbox; /* bounce buffer - can't copy to user space with cli() */ + + + if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { + printk("Hmmm. read() of Applicom card, length %d != expected %d\n", count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); + return -EINVAL; + } + save_flags(flags); + cli(); + + i = 0; + + while (tmp != 2) { + for (i = 0; i < MAX_BOARD; i++) { + if (!apbs[i].RamIO) + continue; + + tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY); + + if (tmp == 2) + break; + + if (tmp > 2) { /* Test octet ready correct */ + Dummy = readb(apbs[i].RamIO + VERS); + restore_flags(flags); + printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n", i, (int) readb(apbs[i].RamIO + DATA_TO_PC_READY)); + DeviceErrorCount++; + return -EIO; + } + Dummy = readb(apbs[i].RamIO + VERS); + + } + if (tmp != 2) { + /* + * FIXME: race on wakeup. O_NDELAY not implemented + * Parallel read threads race. + */ + restore_flags(flags); + interruptible_sleep_on(&FlagSleepRec); + if (signal_pending(current)) + return -EINTR; + save_flags(flags); + cli(); + } } - if (tmp != 2) + + IndexCard = i; + NumCard = i + 1; + st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC); + st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); + + + // memcpy_fromio(&tmpmailbox, apbs[IndexCard].PtrRamToPc, sizeof(struct mailbox)); { - restore_flags(flags); - interruptible_sleep_on (&FlagSleepRec); - if (signal_pending(current)) - return -EINTR; - save_flags(flags); - cli(); + unsigned long from = (unsigned long) apbs[IndexCard].RamIO + RAM_TO_PC; + unsigned char *to = (unsigned char *) &tmpmailbox; + int c; + + for (c = 0; c < sizeof(struct mailbox); c++) + *(to++) = readb(from++); } - } - - IndexCard = i; - NumCard = i+1; - st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC); - st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); - - - // memcpy_fromio(&tmpmailbox, apbs[IndexCard].PtrRamToPc, sizeof(struct mailbox)); - { - unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC; - unsigned char *to = (unsigned char *)&tmpmailbox; - int c; - - for (c=0; c<sizeof(struct mailbox) ; c++) - *(to++) = readb(from++); - } - writeb(1,apbs[IndexCard].RamIO + ACK_FROM_PC_READY); - writeb(1,apbs[IndexCard].RamIO + TYP_ACK_FROM_PC); - writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); - writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), - apbs[IndexCard].RamIO + TIC_ACK_FROM_PC); - writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); - writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY); - writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); + writeb(1, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); + writeb(1, apbs[IndexCard].RamIO + TYP_ACK_FROM_PC); + writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); + writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), apbs[IndexCard].RamIO + TIC_ACK_FROM_PC); + writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); + writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY); + writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); + Dummy = readb(apbs[IndexCard].RamIO + VERS); + restore_flags(flags); #ifdef DEBUG - { int c; + { + int c; - printk("Read from applicom card #%d. struct st_ram_io follows:",NumCard); - - for (c=0; c< sizeof(struct st_ram_io);) - { - printk("\n%5.5X: %2.2X",c,((unsigned char *)&st_loc)[c]); - - for (c++ ; c%8 && c<sizeof(struct st_ram_io); c++) - { - printk(" %2.2X",((unsigned char *)&st_loc)[c]); - } - } + printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard); - printk("\nstruct mailbox follows:"); - - for (c=0; c< sizeof(struct mailbox);) - { - printk("\n%5.5X: %2.2X",c,((unsigned char *)&tmpmailbox)[c]); - - for (c++ ; c%8 && c<sizeof(struct mailbox); c++) - { - printk(" %2.2X",((unsigned char *)&tmpmailbox)[c]); - } - } - printk("\n"); - - } + for (c = 0; c < sizeof(struct st_ram_io);) { + printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]); + + for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) { + printk(" %2.2X", ((unsigned char *) &st_loc)[c]); + } + } + + printk("\nstruct mailbox follows:"); + + for (c = 0; c < sizeof(struct mailbox);) { + printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]); + + for (c++; c % 8 && c < sizeof(struct mailbox); c++) { + printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]); + } + } + printk("\n"); + + } #endif - - /* Je suis stupide. DW. */ - if(copy_to_user (buf, &st_loc, sizeof(struct st_ram_io))) - return -EFAULT; - if(copy_to_user (&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox))) - return -EFAULT; + /* Je suis stupide. DW. */ - return 0; + if (copy_to_user(buf, &st_loc, sizeof(struct st_ram_io))) + return -EFAULT; + if (copy_to_user(&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox))) + return -EFAULT; + + return 0; } static void ac_interrupt(int vec, void *dev_instance, struct pt_regs *regs) { - unsigned int i; - unsigned int FlagInt; - unsigned int LoopCount; - // volatile unsigned char ResetIntBoard; - - // printk("Applicom interrupt on IRQ %d occurred\n", vec); - - LoopCount = 0; - // for(i=boardno;i<MAX_BOARD;i++) /* loop for not configured board */ - // if (apbs[i].RamIO) - // ResetIntBoard = *apbs[i].PtrRamItToPc; /* reset interrupt of unused boards */ - - do - { - FlagInt = FALSE; - for(i=0;i<MAX_BOARD;i++) - { - if (!apbs[i].RamIO) - continue; - - if(readb(apbs[i].RamIO + RAM_IT_TO_PC) != 0) - FlagInt = TRUE; - writeb(0, apbs[i].RamIO + RAM_IT_TO_PC); - - if(readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) - { - printk("APPLICOM driver interrupt err board %d, DataToPcReady = %d\n", - i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY)); - DeviceErrorCount++; - } - if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && - (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) - { - printk("APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n", - i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY)); - DeviceErrorCount++; - } - if(readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) /* mailbox sent by the card ? */ - { - wake_up_interruptible(&FlagSleepRec); - } - if(readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) /* ram i/o free for write by pc ? */ - { - if(waitqueue_active(&apbs[i].FlagSleepSend)) /* process sleep during read ? */ - { - wake_up_interruptible(&apbs[i].FlagSleepSend); - } - } - Dummy = readb(apbs[i].RamIO + VERS); - - if(readb(apbs[i].RamIO + RAM_IT_TO_PC)) - i--; /* There's another int waiting on this card */ - } - if(FlagInt) LoopCount = 0; - else LoopCount++; - } - while(LoopCount < 2); + unsigned int i; + unsigned int FlagInt; + unsigned int LoopCount; + // volatile unsigned char ResetIntBoard; + + // printk("Applicom interrupt on IRQ %d occurred\n", vec); + + LoopCount = 0; + // for(i=boardno;i<MAX_BOARD;i++) /* loop for not configured board */ + // if (apbs[i].RamIO) + // ResetIntBoard = *apbs[i].PtrRamItToPc; /* reset interrupt of unused boards */ + + do { + FlagInt = FALSE; + for (i = 0; i < MAX_BOARD; i++) { + if (!apbs[i].RamIO) + continue; + + if (readb(apbs[i].RamIO + RAM_IT_TO_PC) != 0) + FlagInt = TRUE; + writeb(0, apbs[i].RamIO + RAM_IT_TO_PC); + + if (readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) { + printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n", i + 1, (int) readb(apbs[i].RamIO + DATA_TO_PC_READY)); + DeviceErrorCount++; + } + if ((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) { + printk("APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n", i + 1, (int) readb(apbs[i].RamIO + DATA_FROM_PC_READY)); + DeviceErrorCount++; + } + if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) { /* mailbox sent by the card ? */ + wake_up_interruptible(&FlagSleepRec); + } + if (readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) { /* ram i/o free for write by pc ? */ + if (waitqueue_active(&apbs[i].FlagSleepSend)) { /* process sleep during read ? */ + wake_up_interruptible(&apbs[i].FlagSleepSend); + } + } + Dummy = readb(apbs[i].RamIO + VERS); + + if (readb(apbs[i].RamIO + RAM_IT_TO_PC)) + i--; /* There's another int waiting on this card */ + } + if (FlagInt) + LoopCount = 0; + else + LoopCount++; + } + while (LoopCount < 2); } static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ /* @ ADG ou ATO selon le cas */ + int i; + unsigned char IndexCard; + unsigned long pmem; + volatile unsigned char byte_reset_it; + struct st_ram_io adgl; + unsigned char TmpRamIo[sizeof(struct st_ram_io)]; -{ /* @ ADG ou ATO selon le cas */ - int i; - unsigned char IndexCard; - unsigned long pmem ; - volatile unsigned char byte_reset_it; - struct st_ram_io adgl ; - unsigned char TmpRamIo[sizeof(struct st_ram_io)]; - - - if (copy_from_user (&adgl, (void *)arg,sizeof(struct st_ram_io))) - return -EFAULT; - - IndexCard = adgl.num_card-1; - if(cmd != 0 && cmd != 6 && - ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) - { - printk("APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1); - printk("apbs[%d].RamIO = %lx\n",IndexCard, apbs[IndexCard].RamIO); - return -EINVAL; - } - - switch( cmd ) - { - case 0 : - pmem = apbs[IndexCard].RamIO; - for(i=0;i<sizeof(struct st_ram_io);i++)TmpRamIo[i]=readb(pmem++); - if (copy_to_user((void *)arg, TmpRamIo, sizeof(struct st_ram_io))) - return -EFAULT; - break; - case 1 : - pmem = apbs[IndexCard].RamIO + CONF_END_TEST; - for (i=0;i<4;i++) - adgl.conf_end_test[i] = readb(pmem++); - for (i=0;i<2;i++) - adgl.error_code[i] = readb(pmem++); - for (i=0;i<4;i++) - adgl.parameter_error[i] = readb(pmem++); - pmem = apbs[IndexCard].RamIO + VERS; - adgl.vers = readb(pmem); - pmem = apbs[IndexCard].RamIO + TYPE_CARD; - for (i=0;i<20;i++) - adgl.reserv1[i] = readb(pmem++); - *(int *)&adgl.reserv1[20] = - (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + - (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + - (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) ); - - if (copy_to_user ((void *)arg, &adgl, sizeof(struct st_ram_io))) - return -EFAULT; - break; - case 2 : - pmem = apbs[IndexCard].RamIO + CONF_END_TEST; - for (i=0;i<10;i++) - writeb(0xff, pmem++); - writeb(adgl.data_from_pc_ready, - apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - - writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); + + if (copy_from_user(&adgl, (void *) arg, sizeof(struct st_ram_io))) + return -EFAULT; + + IndexCard = adgl.num_card - 1; + + /* + * FIXME: user can flood the console using bogus ioctls + */ + + if (cmd != 0 && cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { + printk("APPLICOM driver IOCTL, bad board number %d\n", (int) IndexCard + 1); + printk("apbs[%d].RamIO = %lx\n", IndexCard, apbs[IndexCard].RamIO); + return -EINVAL; + } + + /* + * FIXME races between ioctls with multiple clients + */ + + switch (cmd) { + case 0: + pmem = apbs[IndexCard].RamIO; + for (i = 0; i < sizeof(struct st_ram_io); i++) + TmpRamIo[i] = readb(pmem++); + if (copy_to_user((void *) arg, TmpRamIo, sizeof(struct st_ram_io))) + return -EFAULT; + break; + case 1: + pmem = apbs[IndexCard].RamIO + CONF_END_TEST; + for (i = 0; i < 4; i++) + adgl.conf_end_test[i] = readb(pmem++); + for (i = 0; i < 2; i++) + adgl.error_code[i] = readb(pmem++); + for (i = 0; i < 4; i++) + adgl.parameter_error[i] = readb(pmem++); + pmem = apbs[IndexCard].RamIO + VERS; + adgl.vers = readb(pmem); + pmem = apbs[IndexCard].RamIO + TYPE_CARD; + for (i = 0; i < 20; i++) + adgl.reserv1[i] = readb(pmem++); + *(int *) &adgl.reserv1[20] = (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2)); + + if (copy_to_user((void *) arg, &adgl, sizeof(struct st_ram_io))) + return -EFAULT; + break; + case 2: + pmem = apbs[IndexCard].RamIO + CONF_END_TEST; + for (i = 0; i < 10; i++) + writeb(0xff, pmem++); + writeb(adgl.data_from_pc_ready, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); + + writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); + + /* + * FIXME: can trash waitqueue that is active. + */ #if LINUX_VERSION_CODE > 0x20300 - init_waitqueue_head (&FlagSleepRec); + init_waitqueue_head(&FlagSleepRec); #else - FlagSleepRec = NULL; + FlagSleepRec = NULL; #endif - for (i=0;i<MAX_BOARD;i++) - { - if (apbs[i].RamIO) - { + for (i = 0; i < MAX_BOARD; i++) { + if (apbs[i].RamIO) { #if LINUX_VERSION_CODE > 0x20300 - init_waitqueue_head (&apbs[i].FlagSleepSend); + init_waitqueue_head(&apbs[i].FlagSleepSend); #else - apbs[i].FlagSleepSend = NULL; + apbs[i].FlagSleepSend = NULL; #endif - byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC); - } - } - break ; - case 3 : - pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC; - writeb(adgl.tic_des_from_pc, pmem); - break; - case 4 : - pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC; - adgl.tic_owner_to_pc = readb(pmem++); - adgl.numcard_owner_to_pc = readb(pmem); - if (copy_to_user ((void *)arg, &adgl,sizeof(struct st_ram_io))) - return -EFAULT; - break; - case 5 : - writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); - writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); - writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); - writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - break ; - case 6 : - printk("APPLICOM driver release .... V2.8.0\n"); - printk("Number of installed boards . %d\n",(int)numboards); - printk("Segment of board ........... %X\n",(int)mem); - printk("Interrupt IRQ number ....... %d\n",(int)irq); - for(i=0;i<MAX_BOARD;i++) - { - int serial; - char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1]; - - if (!apbs[i].RamIO) - continue; - - - for(serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) - boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); - boardname[serial]=0; - - - printk("Prom version board %d ....... V%d.%d %s", - i+1, - (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4), - (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF), - boardname); - - - serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) ); - - if (serial != 0) - printk (" S/N %d\n", serial); - else - printk("\n"); - } - if(DeviceErrorCount != 0) - printk("DeviceErrorCount ........... %d\n",DeviceErrorCount); - if(ReadErrorCount != 0) - printk("ReadErrorCount ............. %d\n",ReadErrorCount); - if(WriteErrorCount != 0) - printk("WriteErrorCount ............ %d\n",WriteErrorCount); - if(waitqueue_active(&FlagSleepRec)) - printk("Process in read pending\n"); - for(i=0;i<MAX_BOARD;i++) - { - if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend)) - printk("Process in write pending board %d\n",i+1); - } - break; - default : - printk("APPLICOM driver ioctl, unknown function code %d\n",cmd) ; - return -EINVAL; - break; - } - Dummy = readb(apbs[IndexCard].RamIO + VERS); - return 0; + byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC); + } + } + break; + case 3: + pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC; + writeb(adgl.tic_des_from_pc, pmem); + break; + case 4: + pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC; + adgl.tic_owner_to_pc = readb(pmem++); + adgl.numcard_owner_to_pc = readb(pmem); + if (copy_to_user((void *) arg, &adgl, sizeof(struct st_ram_io))) + return -EFAULT; + break; + case 5: + writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); + writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); + writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); + writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); + writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); + break; + case 6: + printk(KERN_INFO "APPLICOM driver release .... V2.8.0\n"); + printk(KERN_INFO "Number of installed boards . %d\n", (int) numboards); + printk(KERN_INFO "Segment of board ........... %X\n", (int) mem); + printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int) irq); + for (i = 0; i < MAX_BOARD; i++) { + int serial; + char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1]; + + if (!apbs[i].RamIO) + continue; + + + for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) + boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); + boardname[serial] = 0; + + + printk(KERN_INFO "Prom version board %d ....... V%d.%d %s", i + 1, (int) (readb(apbs[IndexCard].RamIO + VERS) >> 4), (int) (readb(apbs[IndexCard].RamIO + VERS) & 0xF), boardname); + + + serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2)); + + if (serial != 0) + printk(" S/N %d\n", serial); + else + printk("\n"); + } + if (DeviceErrorCount != 0) + printk(KERN_INFO "DeviceErrorCount ........... %d\n", DeviceErrorCount); + if (ReadErrorCount != 0) + printk(KERN_INFO "ReadErrorCount ............. %d\n", ReadErrorCount); + if (WriteErrorCount != 0) + printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount); + if (waitqueue_active(&FlagSleepRec)) + printk("Process in read pending\n"); + for (i = 0; i < MAX_BOARD; i++) { + if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend)) + printk("Process in write pending board %d\n", i + 1); + } + break; + default: + printk("APPLICOM driver ioctl, unknown function code %d\n", cmd); + return -EINVAL; + break; + } + Dummy = readb(apbs[IndexCard].RamIO + VERS); + return 0; } #ifndef MODULE static int __init applicom_setup(char *str) { int ints[4]; - - (void)get_options(str, 4, ints); + + (void) get_options(str, 4, ints); if (ints[0] > 2) { printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n"); } - + if (ints[0] < 2) { printk("applicom numargs: %d\n", ints[0]); return 0; } - - mem=ints[1]; - irq=ints[2]; + + mem = ints[1]; + irq = ints[2]; return 1; } + #if LINUX_VERSION_CODE > 0x20300 __setup("applicom=", applicom_setup); #endif -#endif /* MODULE */ - +#endif /* MODULE */ diff --git a/drivers/char/atixlmouse.c b/drivers/char/atixlmouse.c index 38de427e6..223793374 100644 --- a/drivers/char/atixlmouse.c +++ b/drivers/char/atixlmouse.c @@ -92,10 +92,14 @@ static int release_mouse(struct inode * inode, struct file * file) static int open_mouse(struct inode * inode, struct file * file) { + /* Lock module as request_irq may sleep */ + MOD_INC_USE_COUNT; if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL)) + { + MOD_DEC_USE_COUNT; return -EBUSY; + } ATIXL_MSE_INT_ON(); /* Interrupts are really enabled here */ - MOD_INC_USE_COUNT; return 0; } @@ -107,7 +111,13 @@ static int __init atixl_busmouse_init(void) { unsigned char a,b,c; - if (check_region(ATIXL_MSE_DATA_PORT, 3)) + /* + * We must request the resource and claim it atomically + * nowdays. We can throw it away on error. Otherwise we + * may race another module load of the same I/O + */ + + if (!request_region(ATIXL_MSE_DATA_PORT, 3, "atixlmouse")) return -EIO; a = inb( ATIXL_MSE_SIGNATURE_PORT ); /* Get signature */ @@ -116,16 +126,20 @@ static int __init atixl_busmouse_init(void) if (( a != b ) && ( a == c )) printk(KERN_INFO "\nATI Inport "); else + { + release_region(ATIXL_MSE_DATA_PORT,3); return -EIO; + } outb(0x80, ATIXL_MSE_CONTROL_PORT); /* Reset the Inport device */ outb(0x07, ATIXL_MSE_CONTROL_PORT); /* Select Internal Register 7 */ outb(0x0a, ATIXL_MSE_DATA_PORT); /* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */ - request_region(ATIXL_MSE_DATA_PORT, 3, "atixl"); - msedev = register_busmouse(&atixlmouse); if (msedev < 0) + { printk("Bus mouse initialisation error.\n"); + release_region(ATIXL_MSE_DATA_PORT,3); /* Was missing */ + } else printk("Bus mouse detected and installed.\n"); return msedev < 0 ? msedev : 0; diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 66dfc0fe5..59adf47bc 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -121,6 +121,7 @@ static unsigned int autoload = 0; #define I2C_GET() (btread(BT848_I2C)&1) #define BURSTOFFSET 76 +#define BTTV_ERRORS 5 /* ----------------------------------------------------------------------- */ @@ -133,7 +134,6 @@ int bttv_get_id(unsigned int card) if (card >= bttv_num) { return -1; } - return bttvs[card].type; } @@ -146,10 +146,7 @@ int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) } btv = &bttvs[card]; - down(&btv->lock); btaor(data, ~mask, BT848_GPIO_OUT_EN); - up(&btv->lock); - return 0; } @@ -167,15 +164,9 @@ int bttv_read_gpio(unsigned int card, unsigned long *data) return -ENODEV; } - down(&btv->lock); - /* prior setting BT848_GPIO_REG_INP is (probably) not needed because we set direct input on init */ - *data = btread(BT848_GPIO_DATA); - - up(&btv->lock); - return 0; } @@ -189,15 +180,9 @@ int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) btv = &bttvs[card]; - down(&btv->lock); - /* prior setting BT848_GPIO_REG_INP is (probably) not needed because direct input is set on init */ - btaor(data & mask, ~mask, BT848_GPIO_DATA); - - up(&btv->lock); - return 0; } @@ -210,11 +195,9 @@ WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card) } btv = &bttvs[card]; - if (bttvs[card].shutdown) { return NULL; } - return &btv->gpioq; } @@ -787,7 +770,7 @@ static struct tvcard tvcards[] = 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0, 1,1,1,1,0 }, { "Hauppauge old", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, + 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, 1,1,0,1,0 }, { "STB", 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, @@ -815,7 +798,7 @@ static struct tvcard tvcards[] = 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0, 1,1,1,1,0 }, { "Hauppauge new (bt878)", - 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, + 4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, 1,1,0,1,0 }, { "MIRO PCTV pro", 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0, @@ -1213,7 +1196,7 @@ static void make_vbitab(struct bttv *btv) unsigned int *pe=(unsigned int *) btv->vbi_even; if (debug) - printk("bttv%d: vbi: po=%08lx pe=%08lx\n", + printk("bttv%d: vbi1: po=%08lx pe=%08lx\n", btv->nr,virt_to_bus(po), virt_to_bus(pe)); *(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0; @@ -1233,8 +1216,10 @@ static void make_vbitab(struct bttv *btv) } *(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16)); *(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); - DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po)); - DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe)); + + if (debug) + printk("bttv%d: vbi2: po=%08lx pe=%08lx\n", + btv->nr,virt_to_bus(po), virt_to_bus(pe)); } static int fmtbppx2[16] = { @@ -1310,7 +1295,7 @@ static int make_prisctab(struct bttv *btv, unsigned int *ro, int shift, csize; if (debug) - printk("bttv%d: prisc: ro=%08lx re=%08lx\n", + printk("bttv%d: prisc1: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); switch(fmt) @@ -1406,6 +1391,10 @@ static int make_prisctab(struct bttv *btv, unsigned int *ro, *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); *(re++)=cpu_to_le32(btv->bus_vbi_odd); + if (debug) + printk("bttv%d: prisc2: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); + return 0; } @@ -1428,7 +1417,7 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro, return make_prisctab(btv, ro, re, vbuf, width, height, palette); if (debug) - printk("bttv%d: vrisc: ro=%08lx re=%08lx\n", + printk("bttv%d: vrisc1: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; @@ -1478,6 +1467,10 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro, *(ro++)=cpu_to_le32(btv->bus_vbi_even); *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); *(re++)=cpu_to_le32(btv->bus_vbi_odd); + + if (debug) + printk("bttv%d: vrisc2: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); return 0; } @@ -1555,7 +1548,7 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) width=btv->win.width; height=btv->win.height; if (debug) - printk("bttv%d: make_clip: pal=%d size=%dx%d, bpl=%d bpp=%d\n", + printk("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n", btv->nr,btv->picture.palette,width,height,bpl,bpp); if(width > 1023) width = 1023; /* sanity check */ @@ -1662,6 +1655,10 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) *(ro++)=cpu_to_le32(btv->bus_vbi_even); *(re++)=cpu_to_le32(BT848_RISC_JUMP); *(re++)=cpu_to_le32(btv->bus_vbi_odd); + + if (debug) + printk("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n", + btv->nr,btv->picture.palette,width,height,bpl,bpp); } /* @@ -1879,7 +1876,7 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) if(btv->gbuf[mp->frame].stat != GBUFFER_UNUSED) return -EBUSY; - if(mp->height <0 || mp->width <0) + if(mp->height < 32 || mp->width < 32) return -EINVAL; if (mp->format >= PALETTEFMT_MAX) return -EINVAL; @@ -1891,12 +1888,6 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) return -EINVAL; /* - * FIXME: Check the format of the grab here. This is probably - * also less restrictive than the normal overlay grabs. Stuff - * like QCIF has meaning as a capture. - */ - - /* * Ok load up the BT848 */ @@ -1906,7 +1897,8 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); if (debug) - printk("bttv%d: cap vgrab: queue %d\n",btv->nr,mp->frame); + printk("bttv%d: cap vgrab: queue %d (%dx%d)\n", + btv->nr,mp->frame,mp->width,mp->height); cli(); btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; @@ -1995,6 +1987,26 @@ static inline void burst(int on) tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0); } +static void bt848_restart(struct bttv *btv) +{ + if (verbose) + printk("bttv%d: resetting chip\n",btv->nr); + btwrite(0xfffffUL, BT848_INT_STAT); + btand(~15, BT848_GPIO_DMA_CTL); + btwrite(0, BT848_SRESET); + btwrite(virt_to_bus(btv->risc_jmp+2), + BT848_RISC_STRT_ADD); + + /* enforce pll reprogramming */ + btv->pll.pll_current = 0; + set_pll(btv); + + btv->errors = 0; + btv->needs_restart = 0; + bt848_set_geo(btv,0); + bt848_set_risc_jmps(btv,-1); +} + /* * Open a bttv card. Right now the flags stuff is just playing */ @@ -2020,6 +2032,8 @@ static int bttv_open(struct video_device *dev, int flags) for (i = 0; i < gbuffers; i++) btv->gbuf[i].stat = GBUFFER_UNUSED; + if (btv->needs_restart) + bt848_restart(btv); burst(0); set_pll(btv); btv->user++; @@ -2117,7 +2131,6 @@ static inline void bt848_sat_v(struct bttv *btv, unsigned long data) btaor(datahi, ~1, BT848_O_CONTROL); } - /* * ioctl routine */ @@ -2126,7 +2139,7 @@ static inline void bt848_sat_v(struct bttv *btv, unsigned long data) static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct bttv *btv=(struct bttv *)dev; - int i,ret; + int i,ret = 0; if (debug) printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd); @@ -2281,7 +2294,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if(copy_from_user(&vw,arg,sizeof(vw))) return -EFAULT; - + if(vw.flags || vw.width < 16 || vw.height < 16) { down(&btv->lock); @@ -2296,6 +2309,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) vw.width &= ~3; } down(&btv->lock); + if (btv->needs_restart) + bt848_restart(btv); btv->win.x=vw.x; btv->win.y=vw.y; btv->win.width=vw.width; @@ -2551,14 +2566,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EINVAL; switch (btv->gbuf[i].stat) { case GBUFFER_UNUSED: - return -EINVAL; + ret = -EINVAL; + break; case GBUFFER_GRABBING: while(btv->gbuf[i].stat==GBUFFER_GRABBING) { if (debug) printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); interruptible_sleep_on(&btv->capq); - if(signal_pending(current)) - return -EINTR; + if(signal_pending(current)) { + ret = -EINTR; + break; + } } /* fall throuth */ case GBUFFER_DONE: @@ -2567,9 +2585,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if (debug) printk("bttv%d: cap sync: buffer %d, retval %d\n",btv->nr,i,ret); btv->gbuf[i].stat = GBUFFER_UNUSED; - return ret; } - return 0; + if (btv->needs_restart) { + down(&btv->lock); + bt848_restart(btv); + up(&btv->lock); + } + return ret; case BTTV_FIELDNR: if(copy_to_user((void *) arg, (void *) &btv->last_field, @@ -2742,6 +2764,11 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { + if (btv->needs_restart) { + down(&btv->lock); + bt848_restart(btv); + up(&btv->lock); + } if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) return -EFAULT; todo-=q; @@ -2796,6 +2823,8 @@ static int vbi_open(struct video_device *dev, int flags) struct bttv *btv=(struct bttv *)(dev-2); down(&btv->lock); + if (btv->needs_restart) + bt848_restart(btv); btv->vbip=VBIBUF_SIZE; btv->vbi_on = 1; bt848_set_risc_jmps(btv,-1); @@ -2938,8 +2967,8 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if(v.tuner||btv->channel) /* Only tuner 0 */ return -EINVAL; strcpy(v.name, "Radio"); - v.rangelow=(int)(87.5*16); - v.rangehigh=(int)(108*16); + v.rangelow=(int)(76*16); /* jp: 76.0MHz - 89.9MHz */ + v.rangehigh=(int)(108*16); /* eu: 87.5MHz - 108.0MHz */ v.flags= 0; /* XXX */ v.mode = 0; /* XXX */ if(copy_to_user(arg,&v,sizeof(v))) @@ -3100,12 +3129,10 @@ static void idcard(int i) /* print which board we have found */ printk(KERN_INFO "bttv%d: model: ",btv->nr); - sprintf(btv->video_dev.name,"BT%d",btv->id); - if (btv->id==848 && btv->revision==0x12) - strcat(btv->video_dev.name,"A"); - strcat(btv->video_dev.name,"("); - strcat(btv->video_dev.name, tvcards[btv->type].name); - strcat(btv->video_dev.name,")"); + sprintf(btv->video_dev.name,"BT%d%s(%.22s)", + btv->id, + (btv->id==848 && btv->revision==0x12) ? "A" : "", + tvcards[btv->type].name); printk("%s\n",btv->video_dev.name); /* board specific initialisations */ @@ -3357,6 +3384,9 @@ static int init_bt848(int i) btv->vbibuf=0; btv->field=btv->last_field=0; + btv->errors=0; + btv->needs_restart=0; + /* i2c */ btv->tuner_type=-1; init_bttv_i2c(btv); @@ -3458,7 +3488,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) { u32 stat,astat; u32 dstat; - int count; + int count,i; struct bttv *btv; btv=(struct bttv *)dev_id; @@ -3498,24 +3528,43 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) btv->field++; } if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) { - printk("bttv%d: irq:%s%s risc_count=%08x\n",btv->nr, - (astat&BT848_INT_SCERR) ? " SCERR" : "", - (astat&BT848_INT_OCERR) ? " OCERR" : "", - btread(BT848_RISC_COUNT)); - bt848_set_risc_jmps(btv,0); - btwrite(0, BT848_SRESET); - btwrite(virt_to_bus(btv->risc_jmp), - BT848_RISC_STRT_ADD); - bt848_set_geo(btv,0); - bt848_set_risc_jmps(btv,-1); -#if 0 - wake_up_interruptible(&btv->vbiq); - wake_up_interruptible(&btv->capq); -#endif + if (verbose) + printk("bttv%d: irq:%s%s risc_count=%08x\n", + btv->nr, + (astat&BT848_INT_SCERR) ? " SCERR" : "", + (astat&BT848_INT_OCERR) ? " OCERR" : "", + btread(BT848_RISC_COUNT)); + btv->errors++; + if (btv->errors < BTTV_ERRORS) { + btand(~15, BT848_GPIO_DMA_CTL); + btwrite(virt_to_bus(btv->risc_jmp+2), + BT848_RISC_STRT_ADD); + bt848_set_geo(btv,0); + bt848_set_risc_jmps(btv,-1); + } else { + if (verbose) + printk("bttv%d: aiee: error loops\n",btv->nr); + /* cancel all outstanding grab requests */ + btv->gq_in = 0; + btv->gq_out = 0; + btv->gq_grab = -1; + for (i = 0; i < gbuffers; i++) + if (btv->gbuf[i].stat == GBUFFER_GRABBING) + btv->gbuf[i].stat = GBUFFER_ERROR; + /* disable DMA */ + btv->risc_cap_odd = 0; + btv->risc_cap_even = 0; + bt848_set_risc_jmps(btv,0); + + btv->needs_restart = 1; + wake_up_interruptible(&btv->vbiq); + wake_up_interruptible(&btv->capq); + } } if (astat&BT848_INT_RISCI) { - IDEBUG(printk ("bttv%d: IRQ_RISCI\n", btv->nr)); + if (debug > 1) + printk("bttv%d: IRQ_RISCI\n",btv->nr); /* captured VBI frame */ if (stat&(1<<28)) @@ -3527,11 +3576,12 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } /* captured full frame */ - if (stat&(2<<28)) + if (stat&(2<<28) && btv->gq_grab != -1) { btv->last_field=btv->field; if (debug) printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab); + do_gettimeofday(&btv->gbuf[btv->gq_grab].tv); btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE; btv->gq_grab = -1; if (btv->gq_in != btv->gq_out) @@ -3662,6 +3712,11 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) btv->id=dev->device; btv->irq=dev->irq; btv->bt848_adr=dev->resource[0].start; + if (!request_mem_region(pci_resource_start(dev,0), + pci_resource_len(dev,0), + "bttv")) { + return -EBUSY; + } if (btv->id >= 878) btv->i2c_command = 0x83; else @@ -3720,15 +3775,15 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) { printk(KERN_ERR "bttv%d: Bad irq number or handler\n", bttv_num); - return -EINVAL; + goto fail; } if (result==-EBUSY) { printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq); - return result; + goto fail; } if (result < 0) - return result; + goto fail; pci_set_master(dev); @@ -3744,11 +3799,16 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) if (!(command&BT878_EN_TBFX)) { printk("bttv: 430FX compatibility could not be enabled\n"); - return -1; + result = -1; + goto fail; } } - return 0; + + fail: + release_mem_region(pci_resource_start(btv->dev,0), + pci_resource_len(btv->dev,0)); + return result; } static int find_bt848(void) @@ -3834,6 +3894,8 @@ static void release_bttv(void) if (radio[btv->nr] && btv->radio_dev.minor != -1) video_unregister_device(&btv->radio_dev); + release_mem_region(pci_resource_start(btv->dev,0), + pci_resource_len(btv->dev,0)); /* wake up any waiting processes because shutdown flag is set, no new processes (in this queue) are expected diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index 3a2cd7e21..c1e9b3e9a 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,22) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,24) #include <linux/types.h> #include <linux/wait.h> @@ -112,7 +112,8 @@ struct bttv_gbuf { #define GBUFFER_GRABBING 1 #define GBUFFER_DONE 2 #define GBUFFER_ERROR 3 - + struct timeval tv; + u16 width; u16 height; u16 fmt; @@ -122,8 +123,7 @@ struct bttv_gbuf { unsigned long re; }; -struct bttv -{ +struct bttv { struct video_device video_dev; struct video_device radio_dev; struct video_device vbi_dev; @@ -193,6 +193,9 @@ struct bttv int i2c_command; int triton1; + int errors; + int needs_restart; + WAIT_QUEUE gpioq; int shutdown; }; diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index 03ff3a033..afc10a697 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -20,7 +20,6 @@ */ #include <linux/module.h> -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/signal.h> @@ -48,8 +47,6 @@ */ /*#define BROKEN_MOUSE*/ -extern int sun_mouse_init(void); - struct busmouse_data { struct miscdevice miscdev; struct busmouse *ops; @@ -70,7 +67,13 @@ struct busmouse_data { #define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(MINOR(dev)) #define MINOR_TO_MOUSE(minor) ((minor) - FIRST_MOUSE) +/* + * List of mice and guarding semaphore. You must take the semaphore + * before you take the misc device semaphore if you need both + */ + static struct busmouse_data *busmouse_data[NR_MICE]; +static DECLARE_MUTEX(mouse_sem); /* a mouse driver just has to interface with these functions * These are !!!OLD!!! Do not use!!! @@ -98,8 +101,7 @@ int add_mouse_buttonchange(int set, int value) /* New interface. !!! Use this one !!! * These routines will most probably be called from interrupt. */ -void -busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons) +void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons) { struct busmouse_data *mse = busmouse_data[mousedev]; int changed; @@ -141,24 +143,21 @@ busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons) } } -void -busmouse_add_movement(int mousedev, int dx, int dy) +void busmouse_add_movement(int mousedev, int dx, int dy) { struct busmouse_data *mse = busmouse_data[mousedev]; busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons); } -void -busmouse_add_buttons(int mousedev, int clear, int eor) +void busmouse_add_buttons(int mousedev, int clear, int eor) { struct busmouse_data *mse = busmouse_data[mousedev]; busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor); } -static int -busmouse_fasync(int fd, struct file *filp, int on) +static int busmouse_fasync(int fd, struct file *filp, int on) { struct busmouse_data *mse = (struct busmouse_data *)filp->private_data; int retval; @@ -169,8 +168,7 @@ busmouse_fasync(int fd, struct file *filp, int on) return 0; } -static int -busmouse_release(struct inode *inode, struct file *file) +static int busmouse_release(struct inode *inode, struct file *file) { struct busmouse_data *mse = (struct busmouse_data *)file->private_data; int ret = 0; @@ -190,33 +188,34 @@ busmouse_release(struct inode *inode, struct file *file) return ret; } -static int -busmouse_open(struct inode *inode, struct file *file) +static int busmouse_open(struct inode *inode, struct file *file) { struct busmouse_data *mse; unsigned long flags; unsigned int mousedev; - int ret = 0; + int ret = -ENODEV; mousedev = DEV_TO_MOUSE(inode->i_rdev); if (mousedev >= NR_MICE) return -EINVAL; + + down(&mouse_sem); mse = busmouse_data[mousedev]; if (!mse) /* shouldn't happen, but... */ - return -ENODEV; - + goto end; + if (mse->ops && mse->ops->open) ret = mse->ops->open(inode, file); if (ret) - return ret; + goto end; file->private_data = mse; if (mse->active++) - return 0; + goto end; MOD_INC_USE_COUNT; @@ -231,18 +230,17 @@ busmouse_open(struct inode *inode, struct file *file) mse->buttons = 7; spin_unlock_irqrestore(&mse->lock, flags); - - return 0; +end: + up(&mouse_sem); + return ret; } -static ssize_t -busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { return -EINVAL; } -static ssize_t -busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct busmouse_data *mse = (struct busmouse_data *)file->private_data; DECLARE_WAITQUEUE(wait, current); @@ -328,8 +326,7 @@ repeat: return count; } -static unsigned int -busmouse_poll(struct file *file, poll_table *wait) +static unsigned int busmouse_poll(struct file *file, poll_table *wait) { struct busmouse_data *mse = (struct busmouse_data *)file->private_data; @@ -351,8 +348,16 @@ struct file_operations busmouse_fops= fasync: busmouse_fasync, }; -int -register_busmouse(struct busmouse *ops) +/** + * register_busmouse - register a bus mouse interface + * @ops: busmouse structure for the mouse + * + * Registers a mouse with the driver. The return is mouse number on + * success and a negative errno code on an error. The passed ops + * structure most not be freed until the mouser is unregistered + */ + +int register_busmouse(struct busmouse *ops) { unsigned int msedev = MINOR_TO_MOUSE(ops->minor); struct busmouse_data *mse; @@ -364,13 +369,18 @@ register_busmouse(struct busmouse *ops) return -EINVAL; } - if (busmouse_data[msedev]) - return -EBUSY; - mse = kmalloc(sizeof(*mse), GFP_KERNEL); if (!mse) return -ENOMEM; + down(&mouse_sem); + if (busmouse_data[msedev]) + { + up(&mouse_sem); + kfree(mse); + return -EBUSY; + } + memset(mse, 0, sizeof(*mse)); mse->miscdev.minor = ops->minor; @@ -385,13 +395,23 @@ register_busmouse(struct busmouse *ops) ret = misc_register(&mse->miscdev); if (!ret) ret = msedev; - + up(&mouse_sem); + return ret; } -int -unregister_busmouse(int mousedev) +/** + * unregister_busmouse - unregister a bus mouse interface + * @mousedev: Mouse number to release + * + * Unregister a previously installed mouse handler. The mousedev + * passed is the return code from a previous call to register_busmouse + */ + + +int unregister_busmouse(int mousedev) { + int err = -EINVAL; if (mousedev < 0) return 0; if (mousedev >= NR_MICE) { @@ -400,32 +420,27 @@ unregister_busmouse(int mousedev) return -EINVAL; } + down(&mouse_sem); + if (!busmouse_data[mousedev]) { printk(KERN_WARNING "busmouse: trying to free free mouse" " on mousedev %d\n", mousedev); - return -EINVAL; + goto fail; } if (busmouse_data[mousedev]->active) { printk(KERN_ERR "busmouse: trying to free active mouse" " on mousedev %d\n", mousedev); - return -EINVAL; + goto fail; } - misc_deregister(&busmouse_data[mousedev]->miscdev); + err=misc_deregister(&busmouse_data[mousedev]->miscdev); kfree(busmouse_data[mousedev]); busmouse_data[mousedev] = NULL; - return 0; -} - -int __init -bus_mouse_init(void) -{ -#ifdef CONFIG_SUN_MOUSE - sun_mouse_init(); -#endif - return 0; +fail: + up(&mouse_sem); + return err; } EXPORT_SYMBOL(busmouse_add_movementbuttons); @@ -433,16 +448,3 @@ EXPORT_SYMBOL(busmouse_add_movement); EXPORT_SYMBOL(busmouse_add_buttons); EXPORT_SYMBOL(register_busmouse); EXPORT_SYMBOL(unregister_busmouse); - -#ifdef MODULE -int -init_module(void) -{ - return bus_mouse_init(); -} - -void -cleanup_module(void) -{ -} -#endif diff --git a/drivers/char/busmouse.h b/drivers/char/busmouse.h index 3626334d9..4ba7c9ce4 100644 --- a/drivers/char/busmouse.h +++ b/drivers/char/busmouse.h @@ -23,6 +23,4 @@ extern void busmouse_add_buttons(int mousedev, int clear, int eor); extern int register_busmouse(struct busmouse *ops); extern int unregister_busmouse(int mousedev); -extern int bus_mouse_init(void); - #endif diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 53939959f..30c7f4f89 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -57,6 +57,7 @@ * Head entry for the doubly linked miscdevice list */ static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list }; +static DECLARE_MUTEX(misc_sem); /* * Assigned numbers, used for dynamic minors @@ -97,32 +98,42 @@ static int misc_read_proc(char *buf, char **start, off_t offset, static int misc_open(struct inode * inode, struct file * file) { int minor = MINOR(inode->i_rdev); - struct miscdevice *c = misc_list.next; + struct miscdevice *c; + int err = -ENODEV; + file->f_op = NULL; + + down(&misc_sem); + + c = misc_list.next; while ((c != &misc_list) && (c->minor != minor)) c = c->next; if (c == &misc_list) { char modname[20]; + up(&misc_sem); sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor); request_module(modname); + down(&misc_sem); c = misc_list.next; while ((c != &misc_list) && (c->minor != minor)) c = c->next; if (c == &misc_list) - return -ENODEV; + goto fail; } if ((file->f_op = c->fops) && file->f_op->open) - return file->f_op->open(inode,file); - else - return -ENODEV; + err=file->f_op->open(inode,file); +fail: + up(&misc_sem); + return err; } static struct file_operations misc_fops = { open: misc_open, }; + /** * misc_register - register a miscellaneous device * @misc: device structure @@ -145,12 +156,17 @@ int misc_register(struct miscdevice * misc) if (misc->next || misc->prev) return -EBUSY; + down(&misc_sem); if (misc->minor == MISC_DYNAMIC_MINOR) { int i = DYNAMIC_MINORS; while (--i >= 0) if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) break; - if (i<0) return -EBUSY; + if (i<0) + { + up(&misc_sem); + return -EBUSY; + } misc->minor = i; } if (misc->minor < DYNAMIC_MINORS) @@ -171,6 +187,7 @@ int misc_register(struct miscdevice * misc) misc->next = misc_list.next; misc->prev->next = misc; misc->next->prev = misc; + up(&misc_sem); return 0; } @@ -189,6 +206,7 @@ int misc_deregister(struct miscdevice * misc) int i = misc->minor; if (!misc->next || !misc->prev) return -EINVAL; + down(&misc_sem); misc->prev->next = misc->next; misc->next->prev = misc->prev; misc->next = NULL; @@ -197,6 +215,7 @@ int misc_deregister(struct miscdevice * misc) if (i < DYNAMIC_MINORS && i>0) { misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); } + up(&misc_sem); return 0; } @@ -206,9 +225,6 @@ EXPORT_SYMBOL(misc_deregister); int __init misc_init(void) { create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL); -#ifdef CONFIG_BUSMOUSE - bus_mouse_init(); -#endif #if defined CONFIG_82C710_MOUSE qpmouse_init(); #endif diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 97014d26a..ea9fded05 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -669,15 +669,15 @@ found: if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) BCD_TO_BIN(year); /* This should never happen... */ - if (year > 10 && year < 44) { + if (year > 20 && year < 48) { epoch = 1980; guess = "ARC console"; - } else if (year >= 70 && year <= 72) { - epoch = 1928; - guess = "Digital DECstation"; - } else if (year < 96) { + } else if (year >= 48 && year < 70) { epoch = 1952; guess = "Digital UNIX"; + } else if (year >= 70 && year < 100) { + epoch = 1928; + guess = "Digital DECstation"; } if (guess) printk("rtc: %s epoch (%lu) detected\n", guess, epoch); diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 2c512ccbf..a29a904dd 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -39,13 +39,17 @@ * * 8/99: Generalized PCI support added. Theodore Ts'o * + * 3/00: Rid circular buffer of redundant xmit_cnt. Fix a + * few races on freeing buffers too. + * Alan Modra <alan@linuxcare.com> + * * This module exports the following rs232 io functions: * * int rs_init(void); */ -static char *serial_version = "4.92"; -static char *serial_revdate = "2000-1-27"; +static char *serial_version = "4.93"; +static char *serial_revdate = "2000-03-20"; /* * Serial driver configuration section. Here are the various options: @@ -98,7 +102,7 @@ static char *serial_revdate = "2000-1-27"; #endif #endif -#ifdef CONFIG_ISAPNP +#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) #ifndef ENABLE_SERIAL_PNP #define ENABLE_SERIAL_PNP #endif @@ -133,7 +137,7 @@ static char *serial_revdate = "2000-1-27"; #define RS_STROBE_TIME (10*HZ) #define RS_ISR_PASS_LIMIT 256 -#if (defined(__i386__) && (CPU==386 || CPU==486)) +#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) #define SERIAL_INLINE #endif @@ -220,7 +224,6 @@ extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned int minor); extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); - static char *serial_name = "Serial driver"; static DECLARE_TASK_QUEUE(tq_serial); @@ -253,7 +256,7 @@ static unsigned long break_pressed; /* break, really ... */ #endif static unsigned detect_uart_irq (struct serial_state * state); -static void autoconfig(struct serial_state * info); +static void autoconfig(struct serial_state * state); static void change_speed(struct async_struct *info, struct termios *old); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -321,9 +324,6 @@ static struct tty_struct *serial_table[NR_PORTS]; static struct termios *serial_termios[NR_PORTS]; static struct termios *serial_termios_locked[NR_PORTS]; -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ @@ -379,7 +379,7 @@ static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) return inb(info->port+1); #endif case SERIAL_IO_MEM: - return readb(info->iomem_base + + return readb((unsigned long) info->iomem_base + (offset<<info->iomem_reg_shift)); #ifdef CONFIG_SERIAL_GSC case SERIAL_IO_GSC: @@ -401,7 +401,7 @@ static _INLINE_ void serial_out(struct async_struct *info, int offset, break; #endif case SERIAL_IO_MEM: - writeb(value, info->iomem_base + + writeb(value, (unsigned long) info->iomem_base + (offset<<info->iomem_reg_shift)); break; #ifdef CONFIG_SERIAL_GSC @@ -481,7 +481,9 @@ static void rs_start(struct tty_struct *tty) return; save_flags(flags); cli(); - if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { + if (info->xmit.head != info->xmit.tail + && info->xmit.buf + && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); } @@ -633,7 +635,7 @@ static _INLINE_ void receive_chars(struct async_struct *info, static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) { int count; - + if (info->x_char) { serial_outp(info, UART_TX, info->x_char); info->state->icount.tx++; @@ -642,8 +644,9 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) *intr_done = 0; return; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || - info->tty->hw_stopped) { + if (info->xmit.head == info->xmit.tail + || info->tty->stopped + || info->tty->hw_stopped) { info->IER &= ~UART_IER_THRI; serial_out(info, UART_IER, info->IER); return; @@ -651,14 +654,16 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) count = info->xmit_fifo_size; do { - serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]); - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + serial_out(info, UART_TX, info->xmit.buf[info->xmit.tail]); + info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); info->state->icount.tx++; - if (--info->xmit_cnt <= 0) + if (info->xmit.head == info->xmit.tail) break; } while (--count > 0); - if (info->xmit_cnt < WAKEUP_CHARS) + if (CIRC_CNT(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) < WAKEUP_CHARS) rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); #ifdef SERIAL_DEBUG_INTR @@ -667,7 +672,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) if (intr_done) *intr_done = 0; - if (info->xmit_cnt <= 0) { + if (info->xmit.head == info->xmit.tail) { info->IER &= ~UART_IER_THRI; serial_out(info, UART_IER, info->IER); } @@ -759,11 +764,11 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt(%d)...", irq); #endif - + info = IRQ_ports[irq]; if (!info) return; - + #ifdef CONFIG_SERIAL_MULTIPORT multi = &rs_multiport[irq]; if (multi->port_monitor) @@ -833,7 +838,7 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_single(%d)...", irq); #endif - + info = IRQ_ports[irq]; if (!info || !info->tty) return; @@ -888,7 +893,7 @@ static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs) #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_multi(%d)...", irq); #endif - + info = IRQ_ports[irq]; if (!info) return; @@ -1026,7 +1031,7 @@ static void rs_timer(void) serial_out(info, UART_IER, info->IER); info = info->next_port; } while (info); -#ifdef CONFIG_SERIAL_MULTIPORT +#ifdef CONFIG_SERIAL_MULTIPORT if (rs_multiport[i].port1) rs_interrupt_multi(i, NULL, NULL); else @@ -1117,10 +1122,10 @@ static int startup(struct async_struct * info) free_page(page); goto errout; } - if (info->xmit_buf) + if (info->xmit.buf) free_page(page); else - info->xmit_buf = (unsigned char *) page; + info->xmit.buf = (unsigned char *) page; #ifdef SERIAL_DEBUG_OPEN printk("starting up ttys%d (irq %d)...", info->line, state->irq); @@ -1298,7 +1303,7 @@ static int startup(struct async_struct * info) if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->xmit.head = info->xmit.tail = 0; /* * Set up serial timers... @@ -1393,9 +1398,10 @@ static void shutdown(struct async_struct * info) free_irq(state->irq, &IRQ_ports[state->irq]); } - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = 0; + if (info->xmit.buf) { + unsigned long pg = (unsigned long) info->xmit.buf; + info->xmit.buf = 0; + free_page(pg); } info->IER = 0; @@ -1570,7 +1576,7 @@ static void change_speed(struct async_struct *info, * when DLL is 0. */ if (((quot & 0xFF) == 0) && (info->state->type == PORT_16C950) && - (info->state->revision == 0x5202)) + (info->state->revision == 0x5201)) quot++; info->quot = quot; @@ -1654,7 +1660,7 @@ static void change_speed(struct async_struct *info, serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); } serial_outp(info, UART_FCR, fcr); /* set fcr */ - } + } restore_flags(flags); } @@ -1666,18 +1672,19 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch) if (serial_paranoia_check(info, tty->device, "rs_put_char")) return; - if (!tty || !info->xmit_buf) + if (!tty || !info->xmit.buf) return; save_flags(flags); cli(); - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + if (CIRC_SPACE(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) == 0) { restore_flags(flags); return; } - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE-1; - info->xmit_cnt++; + info->xmit.buf[info->xmit.head] = ch; + info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); restore_flags(flags); } @@ -1689,8 +1696,10 @@ static void rs_flush_chars(struct tty_struct *tty) if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) return; - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) + if (info->xmit.head == info->xmit.tail + || tty->stopped + || tty->hw_stopped + || !info->xmit.buf) return; save_flags(flags); cli(); @@ -1709,16 +1718,19 @@ static int rs_write(struct tty_struct * tty, int from_user, if (serial_paranoia_check(info, tty->device, "rs_write")) return 0; - if (!tty || !info->xmit_buf || !tmp_buf) + if (!tty || !info->xmit.buf || !tmp_buf) return 0; save_flags(flags); if (from_user) { down(&tmp_buf_sem); while (1) { - c = MIN(count, - MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + int c1; + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; if (c <= 0) break; @@ -1729,12 +1741,14 @@ static int rs_write(struct tty_struct * tty, int from_user, break; } cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & + c1 = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); + info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; restore_flags(flags); buf += c; count -= c; @@ -1742,27 +1756,29 @@ static int rs_write(struct tty_struct * tty, int from_user, } up(&tmp_buf_sem); } else { + cli(); while (1) { - cli(); - c = MIN(count, - MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; if (c <= 0) { - restore_flags(flags); break; } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - restore_flags(flags); buf += c; count -= c; ret += c; } + restore_flags(flags); } - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped && - !(info->IER & UART_IER_THRI)) { + if (info->xmit.head != info->xmit.tail + && !tty->stopped + && !tty->hw_stopped + && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); } @@ -1772,14 +1788,10 @@ static int rs_write(struct tty_struct * tty, int from_user, static int rs_write_room(struct tty_struct *tty) { struct async_struct *info = (struct async_struct *)tty->driver_data; - int ret; - + if (serial_paranoia_check(info, tty->device, "rs_write_room")) return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; + return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } static int rs_chars_in_buffer(struct tty_struct *tty) @@ -1788,7 +1800,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty) if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) return 0; - return info->xmit_cnt; + return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } static void rs_flush_buffer(struct tty_struct *tty) @@ -1799,7 +1811,7 @@ static void rs_flush_buffer(struct tty_struct *tty) if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) return; save_flags(flags); cli(); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->xmit.head = info->xmit.tail = 0; restore_flags(flags); wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && @@ -2071,8 +2083,9 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value) * interrupt happens). */ if (info->x_char || - ((info->xmit_cnt > 0) && !info->tty->stopped && - !info->tty->hw_stopped)) + ((CIRC_CNT(info->xmit.head, info->xmit.tail, + SERIAL_XMIT_SIZE) > 0) && + !info->tty->stopped && !info->tty->hw_stopped)) result &= TIOCSER_TEMT; if (copy_to_user(value, &result, sizeof(int))) @@ -2708,8 +2721,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) char_time = char_time / 5; if (char_time == 0) char_time = 1; - if (timeout) - char_time = MIN(char_time, timeout); + if (timeout && timeout < char_time) + char_time = timeout; /* * If the transmitter hasn't cleared in twice the approximate * amount of time to send the entire FIFO, it probably won't @@ -3060,7 +3073,7 @@ static inline int line_info(char *buf, struct serial_state *state) int ret; unsigned long flags; - ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", + ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", state->line, uart_config[state->type].name, state->port, state->irq); @@ -3083,9 +3096,9 @@ static inline int line_info(char *buf, struct serial_state *state) } save_flags(flags); cli(); status = serial_in(info, UART_MSR); - control = info ? info->MCR : serial_in(info, UART_MCR); + control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR); restore_flags(flags); - + stat_buf[0] = 0; stat_buf[1] = 0; if (control & UART_MCR_RTS) @@ -3403,7 +3416,7 @@ static void autoconfig(struct serial_state * state) state->type = PORT_UNKNOWN; #ifdef SERIAL_DEBUG_AUTOCONF - printk("Testing ttyS%d (0x%04x, 0x%04x)...\n", state->line, + printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line, state->port, (unsigned) state->iomem_base); #endif @@ -3743,15 +3756,10 @@ pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable) /* enable/disable interrupts */ p = ioremap(PCI_BASE_ADDRESS(dev, 0), 0x80); - if (dev->vendor == PCI_VENDOR_ID_PANACOM) { - scratch = readl(p + 0x4c); - if (enable) - scratch |= 0x40; - else - scratch &= ~0x40; - writel(scratch, p + 0x4c); - } else - writel(enable ? 0x41 : 0x00, p + 0x4c); + scratch = 0x41; + if (dev->vendor == PCI_VENDOR_ID_PANACOM) + scratch = 0x43; + writel(enable ? scratch : 0x00, (unsigned long)p + 0x4c); iounmap(p); if (!enable) @@ -3806,7 +3814,7 @@ pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable) break; } - writew(readw(p + 0x28) & data, p + 0x28); + writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); iounmap(p); return 0; } @@ -4181,6 +4189,19 @@ static struct pci_board pci_boards[] __initdata = { { PCI_VENDOR_ID_USR, 0x1008, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE0, 1, 115200 }, + /* Titan Electronic cards */ + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE0, 1, 921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE0, 2, 921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE0, 4, 921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE0, 4, 921600 }, /* * Untested PCI modems, sent in from various folks... */ @@ -4188,10 +4209,9 @@ static struct pci_board pci_boards[] __initdata = { { PCI_VENDOR_ID_ROCKWELL, 0x1004, 0x1048, 0x1500, SPCI_FL_BASE1, 1, 115200 }, -#ifdef CONFIG_DDB5074 +#if 0 /* No definition for PCI_DEVICE_ID_NEC_NILE4 */ /* * NEC Vrc-5074 (Nile 4) builtin UART. - * Conditionally compiled in since this is a motherboard device. */ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, PCI_ANY_ID, PCI_ANY_ID, @@ -4306,18 +4326,41 @@ static void __init probe_serial_pci(void) #ifdef ENABLE_SERIAL_PNP static struct pci_board pnp_devices[] __initdata = { + /* Motorola VoiceSURFR 56K Modem */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, /* Rockwell 56K ACF II Fax+Data+Voice Modem */ { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_NO_SHIRQ | SPCI_FL_PNPDEFAULT, + 1, 115200 }, + /* AZT3005 PnP SOUND DEVICE */ + { ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* Best Data Products Inc. Smart One 336F PnP Modem */ + { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336), 0, 0, SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, /* Boca Research 33,600 ACF Modem */ { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400), 0, 0, SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - /* Best Data Products Inc. Smart One 336F PnP Modem */ - { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336), 0, 0, + /* Creative Modem Blaster Flash56 DI5601-1 */ + { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* Creative Modem Blaster V.90 DI5660 */ + { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* Pace 56 Voice Internal Plug & Play Modem */ + { ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430), 0, 0, SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, /* SupraExpress 28.8 Data/Fax PnP modem */ { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310), 0, 0, SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* US Robotics Sporster 33600 Modem */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* U.S. Robotics 56K FAX INT */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* These ID's are taken from M$ documentation */ /* Compaq 14400 Modem */ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000), 0, 0, @@ -4334,6 +4377,24 @@ static struct pci_board pnp_devices[] __initdata = { { 0, } }; +static void inline avoid_irq_share(struct pci_dev *dev) +{ + int i, map = 0x1FF8; + struct serial_state *state = rs_table; + struct isapnp_irq *irq; + struct isapnp_resources *res = dev->sysdata; + + for (i = 0; i < NR_PORTS; i++) { + if (state->type != PORT_UNKNOWN) + clear_bit(state->irq, &map); + state++; + } + + for ( ; res; res = res->alt) + for(irq = res->irq; irq; irq = irq->next) + irq->map = map; +} + static void __init probe_serial_pnp(void) { struct pci_dev *dev = NULL; @@ -4352,9 +4413,9 @@ static void __init probe_serial_pnp(void) for (board = pnp_devices; board->vendor; board++) { while ((dev = isapnp_find_dev(NULL, board->vendor, board->device, dev))) { - - start_pci_pnp_board(dev, board); - + if (board->flags & SPCI_FL_NO_SHIRQ) + avoid_irq_share(dev); + start_pci_pnp_board(dev, board); } } @@ -4417,7 +4478,11 @@ int __init rs_init(void) #if (LINUX_VERSION_CODE > 0x20100) serial_driver.driver_name = "serial"; #endif +#if (LINUX_VERSION_CODE > 0x2032D) serial_driver.name = "tts/%d"; +#else + serial_driver.name = "ttyS"; +#endif serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET; serial_driver.num = NR_PORTS; @@ -4461,7 +4526,11 @@ int __init rs_init(void) * major number and the subtype code. */ callout_driver = serial_driver; +#if (LINUX_VERSION_CODE > 0x2032D) callout_driver.name = "cua/%d"; +#else + callout_driver.name = "cua"; +#endif callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; #if (LINUX_VERSION_CODE >= 131343) @@ -4503,7 +4572,7 @@ int __init rs_init(void) && (state->flags & ASYNC_AUTO_IRQ) && (state->port != 0)) state->irq = detect_uart_irq(state); - printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n", + printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n", state->line + SERIAL_DEV_OFFSET, (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", state->port, state->irq, @@ -4538,7 +4607,7 @@ int __init rs_init(void) * The port is then probed and if neccessary the IRQ is autodetected * If this fails an error is returned. * - * On success the port is ready to use and the line number is returned. + * On success the port is ready to use and the line number is returned. */ int register_serial(struct serial_struct *req) @@ -4548,8 +4617,7 @@ int register_serial(struct serial_struct *req) struct serial_state *state; struct async_struct *info; - save_flags(flags); - cli(); + save_flags(flags); cli(); for (i = 0; i < NR_PORTS; i++) { if ((rs_table[i].port == req->port) && (rs_table[i].iomem_base == req->iomem_base)) @@ -4568,7 +4636,7 @@ int register_serial(struct serial_struct *req) state = &rs_table[i]; if (rs_table[i].count) { restore_flags(flags); - printk("Couldn't configure serial #%d (port=%d,irq=%d): " + printk("Couldn't configure serial #%d (port=%ld,irq=%d): " "device already open\n", i, req->port, req->irq); return -1; } @@ -4598,12 +4666,11 @@ int register_serial(struct serial_struct *req) if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state)) state->irq = detect_uart_irq(state); - printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", + printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", state->line + SERIAL_DEV_OFFSET, state->iomem_base ? "iomem" : "port", state->iomem_base ? (unsigned long)state->iomem_base : - (unsigned long)state->port, - state->irq, uart_config[state->type].name); + state->port, state->irq, uart_config[state->type].name); tty_register_devfs(&serial_driver, 0, serial_driver.minor_start + state->line); tty_register_devfs(&callout_driver, 0, @@ -4625,8 +4692,7 @@ void unregister_serial(int line) unsigned long flags; struct serial_state *state = &rs_table[line]; - save_flags(flags); - cli(); + save_flags(flags); cli(); if (state->info && state->info->tty) tty_hangup(state->info->tty); state->type = PORT_UNKNOWN; @@ -4642,12 +4708,7 @@ void unregister_serial(int line) } #ifdef MODULE -int init_module(void) -{ - return rs_init(); -} - -void cleanup_module(void) +void rs_fini(void) { unsigned long flags; int e1, e2; @@ -4655,8 +4716,7 @@ void cleanup_module(void) struct async_struct *info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - save_flags(flags); - cli(); + save_flags(flags); cli(); timer_active &= ~(1 << RS_TIMER); timer_table[RS_TIMER].fn = NULL; timer_table[RS_TIMER].expires = 0; @@ -4693,12 +4753,16 @@ void cleanup_module(void) } #endif if (tmp_buf) { - free_page((unsigned long) tmp_buf); + unsigned long pg = (unsigned long) tmp_buf; tmp_buf = NULL; + free_page(pg); } } #endif /* MODULE */ +module_init(rs_init); +module_exit(rs_fini); + /* * ------------------------------------------------------------ @@ -4960,6 +5024,6 @@ void __init serial_console_init(void) /* Local variables: - compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -DCPU=686 -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" + compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" End: */ diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 48e426623..67deb7f27 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -28,7 +28,7 @@ extern void wakeup_bdflush(int); extern void reset_vc(unsigned int); extern int console_loglevel; -extern struct vfsmount *vfsmntlist; +extern struct list_head super_blocks; /* Machine specific power off function */ void (*sysrq_power_off)(void) = NULL; @@ -174,22 +174,16 @@ static int is_local_disk(kdev_t dev) /* Guess if the device is a local hard } } -static void go_sync(kdev_t dev, int remount_flag) +static void go_sync(struct super_block *sb, int remount_flag) { printk(KERN_INFO "%sing device %s ... ", remount_flag ? "Remount" : "Sync", - kdevname(dev)); + kdevname(sb->s_dev)); if (remount_flag) { /* Remount R/O */ - struct super_block *sb = get_super(dev); - struct vfsmount *vfsmnt; int ret, flags; struct list_head *p; - if (!sb) { - printk("Superblock not found\n"); - return; - } if (sb->s_flags & MS_RDONLY) { printk("R/O\n"); return; @@ -204,7 +198,7 @@ static void go_sync(kdev_t dev, int remount_flag) } file_list_unlock(); DQUOT_OFF(sb); - fsync_dev(dev); + fsync_dev(sb->s_dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { ret = sb->s_op->remount_fs(sb, &flags, NULL); @@ -217,7 +211,7 @@ static void go_sync(kdev_t dev, int remount_flag) } else printk("nothing to do\n"); } else { - fsync_dev(dev); /* Sync only */ + fsync_dev(sb->s_dev); /* Sync only */ printk("OK\n"); } } @@ -233,20 +227,24 @@ int emergency_sync_scheduled; void do_emergency_sync(void) { - struct vfsmount *mnt; + struct super_block *sb; int remount_flag; lock_kernel(); remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT); emergency_sync_scheduled = 0; - for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next) - if (is_local_disk(mnt->mnt_dev)) - go_sync(mnt->mnt_dev, remount_flag); - - for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next) - if (!is_local_disk(mnt->mnt_dev) && MAJOR(mnt->mnt_dev)) - go_sync(mnt->mnt_dev, remount_flag); + for (sb = sb_entry(super_blocks.next); + sb != sb_entry(&super_blocks); + sb = sb_entry(sb->s_list.next)) + if (is_local_disk(sb->s_dev)) + go_sync(sb, remount_flag); + + for (sb = sb_entry(super_blocks.next); + sb != sb_entry(&super_blocks); + sb = sb_entry(sb->s_list.next)) + if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev)) + go_sync(sb, remount_flag); unlock_kernel(); printk(KERN_INFO "Done.\n"); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e1e504b79..1e0c22ee6 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2278,9 +2278,6 @@ void __init tty_init(void) #ifdef CONFIG_ESPSERIAL /* init ESP before rs, so rs doesn't see the port */ espserial_init(); #endif -#ifdef CONFIG_SERIAL - rs_init(); -#endif #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) vme_scc_init(); #endif diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index 029a76bd4..0ce42945d 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -159,10 +159,6 @@ static int wdt_status(void) * Handle an interrupt from the board. These are raised when the status * map changes in what the board considers an interesting way. That means * a failure condition occuring. - * - * FIXME: We need to pass a dev_id as the PCI card can share irqs - * although its arguably a _very_ dumb idea to share watchdog - * irq lines */ void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -494,7 +490,7 @@ void cleanup_module(void) int __init wdt_init(void) { printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq); - if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL)) + if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", &wdt_miscdev)) { printk(KERN_ERR "IRQ %d is not free.\n", irq); return -EIO; |