summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-27 23:54:12 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-27 23:54:12 +0000
commitd3e71cb08747743fce908122bab08b479eb403a5 (patch)
treecbec6948fdbdee9af81cf3ecfb504070d2745d7b /drivers/char
parentfe7ff1706e323d0e5ed83972960a1ecc1ee538b3 (diff)
Merge with Linux 2.3.99-pre3.
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/acquirewdt.c10
-rw-r--r--drivers/char/amigamouse.c6
-rw-r--r--drivers/char/amiserial.c2
-rw-r--r--drivers/char/applicom.c1167
-rw-r--r--drivers/char/atixlmouse.c22
-rw-r--r--drivers/char/bttv.c206
-rw-r--r--drivers/char/bttv.h11
-rw-r--r--drivers/char/busmouse.c126
-rw-r--r--drivers/char/busmouse.h2
-rw-r--r--drivers/char/misc.c34
-rw-r--r--drivers/char/rtc.c10
-rw-r--r--drivers/char/serial.c290
-rw-r--r--drivers/char/sysrq.c36
-rw-r--r--drivers/char/tty_io.c3
-rw-r--r--drivers/char/wdt.c6
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;