diff options
Diffstat (limited to 'drivers/char')
88 files changed, 4840 insertions, 4825 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9e43e39..d0a6dc5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -191,7 +191,7 @@ config MOXA_INTELLIO module will be called moxa. config MOXA_SMARTIO - tristate "Moxa SmartIO support" + tristate "Moxa SmartIO support (OBSOLETE)" depends on SERIAL_NONSTANDARD help Say Y here if you have a Moxa SmartIO multiport serial card. @@ -202,7 +202,7 @@ config MOXA_SMARTIO here. config MOXA_SMARTIO_NEW - tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)" + tristate "Moxa SmartIO support v. 2.0" depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) help Say Y here if you have a Moxa SmartIO multiport serial card and/or @@ -610,6 +610,13 @@ config HVC_RTAS help IBM Console device driver which makes use of RTAS +config HVC_BEAT + bool "Toshiba's Beat Hypervisor Console support" + depends on PPC_CELLEB + select HVC_DRIVER + help + Toshiba's Cell Reference Set Beat Console device driver + config HVCS tristate "IBM Hypervisor Virtual Console Server support" depends on PPC_PSERIES diff --git a/drivers/char/Makefile b/drivers/char/Makefile index fc11063..ae8567c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o +obj-$(CONFIG_HVC_BEAT) += hvc_beat.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o @@ -59,6 +60,8 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o +obj-$(CONFIG_APM_EMULATION) += apm-emulation.o + obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index feb4ac8..0e2b72f 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -527,10 +527,8 @@ static void do_softint(unsigned long private_) if (!tty) return; - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } } /* @@ -904,8 +902,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count if (!info->xmit.buf) return 0; - local_save_flags(flags); - local_irq_disable(); + local_irq_save(flags); while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, @@ -968,7 +965,6 @@ static void rs_flush_buffer(struct tty_struct *tty) local_irq_save(flags); info->xmit.head = info->xmit.tail = 0; local_irq_restore(flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c new file mode 100644 index 0000000..179c7a3 --- /dev/null +++ b/drivers/char/apm-emulation.c @@ -0,0 +1,672 @@ +/* + * bios-less APM driver for ARM Linux + * Jamey Hicks <jamey@crl.dec.com> + * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) + * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Microsoft at: + * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + */ +#include <linux/module.h> +#include <linux/poll.h> +#include <linux/slab.h> +#include <linux/proc_fs.h> +#include <linux/miscdevice.h> +#include <linux/apm_bios.h> +#include <linux/capability.h> +#include <linux/sched.h> +#include <linux/pm.h> +#include <linux/apm-emulation.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/init.h> +#include <linux/completion.h> +#include <linux/kthread.h> +#include <linux/delay.h> + +#include <asm/system.h> + +/* + * The apm_bios device is one of the misc char devices. + * This is its minor number. + */ +#define APM_MINOR_DEV 134 + +/* + * See Documentation/Config.help for the configuration options. + * + * Various options can be changed at boot time as follows: + * (We allow underscores for compatibility with the modules code) + * apm=on/off enable/disable APM + */ + +/* + * Maximum number of events stored + */ +#define APM_MAX_EVENTS 16 + +struct apm_queue { + unsigned int event_head; + unsigned int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; + +/* + * The per-file APM data + */ +struct apm_user { + struct list_head list; + + unsigned int suser: 1; + unsigned int writer: 1; + unsigned int reader: 1; + + int suspend_result; + unsigned int suspend_state; +#define SUSPEND_NONE 0 /* no suspend pending */ +#define SUSPEND_PENDING 1 /* suspend pending read */ +#define SUSPEND_READ 2 /* suspend read, pending ack */ +#define SUSPEND_ACKED 3 /* suspend acked */ +#define SUSPEND_WAIT 4 /* waiting for suspend */ +#define SUSPEND_DONE 5 /* suspend completed */ + + struct apm_queue queue; +}; + +/* + * Local variables + */ +static int suspends_pending; +static int apm_disabled; +static struct task_struct *kapmd_tsk; + +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); + +/* + * This is a list of everyone who has opened /dev/apm_bios + */ +static DECLARE_RWSEM(user_list_lock); +static LIST_HEAD(apm_user_list); + +/* + * kapmd info. kapmd provides us a process context to handle + * "APM" events within - specifically necessary if we're going + * to be suspending the system. + */ +static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); +static DEFINE_SPINLOCK(kapmd_queue_lock); +static struct apm_queue kapmd_queue; + +static DEFINE_MUTEX(state_lock); + +static const char driver_version[] = "1.13"; /* no spaces */ + + + +/* + * Compatibility cruft until the IPAQ people move over to the new + * interface. + */ +static void __apm_get_power_status(struct apm_power_info *info) +{ +} + +/* + * This allows machines to provide their own "apm get power status" function. + */ +void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; +EXPORT_SYMBOL(apm_get_power_status); + + +/* + * APM event queue management. + */ +static inline int queue_empty(struct apm_queue *q) +{ + return q->event_head == q->event_tail; +} + +static inline apm_event_t queue_get_event(struct apm_queue *q) +{ + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + return q->events[q->event_tail]; +} + +static void queue_add_event(struct apm_queue *q, apm_event_t event) +{ + q->event_head = (q->event_head + 1) % APM_MAX_EVENTS; + if (q->event_head == q->event_tail) { + static int notified; + + if (notified++ == 0) + printk(KERN_ERR "apm: an event queue overflowed\n"); + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + } + q->events[q->event_head] = event; +} + +static void queue_event(apm_event_t event) +{ + struct apm_user *as; + + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as->reader) + queue_add_event(&as->queue, event); + } + up_read(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); +} + +/* + * queue_suspend_event - queue an APM suspend event. + * + * Check that we're in a state where we can suspend. If not, + * return -EBUSY. Otherwise, queue an event to all "writer" + * users. If there are no "writer" users, return '1' to + * indicate that we can immediately suspend. + */ +static int queue_suspend_event(apm_event_t event, struct apm_user *sender) +{ + struct apm_user *as; + int ret = 1; + + mutex_lock(&state_lock); + down_read(&user_list_lock); + + /* + * If a thread is still processing, we can't suspend, so reject + * the request. + */ + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader && as->writer && as->suser && + as->suspend_state != SUSPEND_NONE) { + ret = -EBUSY; + goto out; + } + } + + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader && as->writer && as->suser) { + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + queue_add_event(&as->queue, event); + ret = 0; + } + } + out: + up_read(&user_list_lock); + mutex_unlock(&state_lock); + wake_up_interruptible(&apm_waitqueue); + return ret; +} + +static void apm_suspend(void) +{ + struct apm_user *as; + int err = pm_suspend(PM_SUSPEND_MEM); + + /* + * Anyone on the APM queues will think we're still suspended. + * Send a message so everyone knows we're now awake again. + */ + queue_event(APM_NORMAL_RESUME); + + /* + * Finally, wake up anyone who is sleeping on the suspend. + */ + mutex_lock(&state_lock); + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as->suspend_state == SUSPEND_WAIT || + as->suspend_state == SUSPEND_ACKED) { + as->suspend_result = err; + as->suspend_state = SUSPEND_DONE; + } + } + up_read(&user_list_lock); + mutex_unlock(&state_lock); + + wake_up(&apm_suspend_waitqueue); +} + +static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) +{ + struct apm_user *as = fp->private_data; + apm_event_t event; + int i = count, ret = 0; + + if (count < sizeof(apm_event_t)) + return -EINVAL; + + if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) + return -EAGAIN; + + wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); + + while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { + event = queue_get_event(&as->queue); + + ret = -EFAULT; + if (copy_to_user(buf, &event, sizeof(event))) + break; + + mutex_lock(&state_lock); + if (as->suspend_state == SUSPEND_PENDING && + (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) + as->suspend_state = SUSPEND_READ; + mutex_unlock(&state_lock); + + buf += sizeof(event); + i -= sizeof(event); + } + + if (i < count) + ret = count - i; + + return ret; +} + +static unsigned int apm_poll(struct file *fp, poll_table * wait) +{ + struct apm_user *as = fp->private_data; + + poll_wait(fp, &apm_waitqueue, wait); + return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM; +} + +/* + * apm_ioctl - handle APM ioctl + * + * APM_IOC_SUSPEND + * This IOCTL is overloaded, and performs two functions. It is used to: + * - initiate a suspend + * - acknowledge a suspend read from /dev/apm_bios. + * Only when everyone who has opened /dev/apm_bios with write permission + * has acknowledge does the actual suspend happen. + */ +static int +apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) +{ + struct apm_user *as = filp->private_data; + unsigned long flags; + int err = -EINVAL; + + if (!as->suser || !as->writer) + return -EPERM; + + switch (cmd) { + case APM_IOC_SUSPEND: + mutex_lock(&state_lock); + + as->suspend_result = -EINTR; + + if (as->suspend_state == SUSPEND_READ) { + int pending; + + /* + * If we read a suspend command from /dev/apm_bios, + * then the corresponding APM_IOC_SUSPEND ioctl is + * interpreted as an acknowledge. + */ + as->suspend_state = SUSPEND_ACKED; + suspends_pending--; + pending = suspends_pending == 0; + mutex_unlock(&state_lock); + + /* + * If there are no further acknowledges required, + * suspend the system. + */ + if (pending) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there + * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + wait_event(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + } else { + as->suspend_state = SUSPEND_WAIT; + mutex_unlock(&state_lock); + + /* + * Otherwise it is a request to suspend the system. + * Queue an event for all readers, and expect an + * acknowledge from all writers who haven't already + * acknowledged. + */ + err = queue_suspend_event(APM_USER_SUSPEND, as); + if (err < 0) { + /* + * Avoid taking the lock here - this + * should be fine. + */ + as->suspend_state = SUSPEND_NONE; + break; + } + + if (err > 0) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there + * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + wait_event_interruptible(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + } + + current->flags = flags; + + mutex_lock(&state_lock); + err = as->suspend_result; + as->suspend_state = SUSPEND_NONE; + mutex_unlock(&state_lock); + break; + } + + return err; +} + +static int apm_release(struct inode * inode, struct file * filp) +{ + struct apm_user *as = filp->private_data; + int pending = 0; + + filp->private_data = NULL; + + down_write(&user_list_lock); + list_del(&as->list); + up_write(&user_list_lock); + + /* + * We are now unhooked from the chain. As far as new + * events are concerned, we no longer exist. However, we + * need to balance suspends_pending, which means the + * possibility of sleeping. + */ + mutex_lock(&state_lock); + if (as->suspend_state != SUSPEND_NONE) { + suspends_pending -= 1; + pending = suspends_pending == 0; + } + mutex_unlock(&state_lock); + if (pending) + apm_suspend(); + + kfree(as); + return 0; +} + +static int apm_open(struct inode * inode, struct file * filp) +{ + struct apm_user *as; + + as = kzalloc(sizeof(*as), GFP_KERNEL); + if (as) { + /* + * XXX - this is a tiny bit broken, when we consider BSD + * process accounting. If the device is opened by root, we + * instantly flag that we used superuser privs. Who knows, + * we might close the device immediately without doing a + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); + as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; + as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; + + down_write(&user_list_lock); + list_add(&as->list, &apm_user_list); + up_write(&user_list_lock); + + filp->private_data = as; + } + + return as ? 0 : -ENOMEM; +} + +static struct file_operations apm_bios_fops = { + .owner = THIS_MODULE, + .read = apm_read, + .poll = apm_poll, + .ioctl = apm_ioctl, + .open = apm_open, + .release = apm_release, +}; + +static struct miscdevice apm_device = { + .minor = APM_MINOR_DEV, + .name = "apm_bios", + .fops = &apm_bios_fops +}; + + +#ifdef CONFIG_PROC_FS +/* + * Arguments, with symbols from linux/apm_bios.h. + * + * 0) Linux driver version (this will change if format changes) + * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. + * 2) APM flags from APM Installation Check (0x00): + * bit 0: APM_16_BIT_SUPPORT + * bit 1: APM_32_BIT_SUPPORT + * bit 2: APM_IDLE_SLOWS_CLOCK + * bit 3: APM_BIOS_DISABLED + * bit 4: APM_BIOS_DISENGAGED + * 3) AC line status + * 0x00: Off-line + * 0x01: On-line + * 0x02: On backup power (BIOS >= 1.1 only) + * 0xff: Unknown + * 4) Battery status + * 0x00: High + * 0x01: Low + * 0x02: Critical + * 0x03: Charging + * 0x04: Selected battery not present (BIOS >= 1.2 only) + * 0xff: Unknown + * 5) Battery flag + * bit 0: High + * bit 1: Low + * bit 2: Critical + * bit 3: Charging + * bit 7: No system battery + * 0xff: Unknown + * 6) Remaining battery life (percentage of charge): + * 0-100: valid + * -1: Unknown + * 7) Remaining battery life (time units): + * Number of remaining minutes or seconds + * -1: Unknown + * 8) min = minutes; sec = seconds + */ +static int apm_get_info(char *buf, char **start, off_t fpos, int length) +{ + struct apm_power_info info; + char *units; + int ret; + + info.ac_line_status = 0xff; + info.battery_status = 0xff; + info.battery_flag = 0xff; + info.battery_life = -1; + info.time = -1; + info.units = -1; + + if (apm_get_power_status) + apm_get_power_status(&info); + + switch (info.units) { + default: units = "?"; break; + case 0: units = "min"; break; + case 1: units = "sec"; break; + } + + ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, APM_32_BIT_SUPPORT, + info.ac_line_status, info.battery_status, + info.battery_flag, info.battery_life, + info.time, units); + + return ret; +} +#endif + +static int kapmd(void *arg) +{ + do { + apm_event_t event; + int ret; + + wait_event_interruptible(kapmd_wait, + !queue_empty(&kapmd_queue) || kthread_should_stop()); + + if (kthread_should_stop()) + break; + + spin_lock_irq(&kapmd_queue_lock); + event = 0; + if (!queue_empty(&kapmd_queue)) + event = queue_get_event(&kapmd_queue); + spin_unlock_irq(&kapmd_queue_lock); + + switch (event) { + case 0: + break; + + case APM_LOW_BATTERY: + case APM_POWER_STATUS_CHANGE: + queue_event(event); + break; + + case APM_USER_SUSPEND: + case APM_SYS_SUSPEND: + ret = queue_suspend_event(event, NULL); + if (ret < 0) { + /* + * We were busy. Try again in 50ms. + */ + queue_add_event(&kapmd_queue, event); + msleep(50); + } + if (ret > 0) + apm_suspend(); + break; + + case APM_CRITICAL_SUSPEND: + apm_suspend(); + break; + } + } while (1); + + return 0; +} + +static int __init apm_init(void) +{ + int ret; + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + return -ENODEV; + } + + kapmd_tsk = kthread_create(kapmd, NULL, "kapmd"); + if (IS_ERR(kapmd_tsk)) { + ret = PTR_ERR(kapmd_tsk); + kapmd_tsk = NULL; + return ret; + } + kapmd_tsk->flags |= PF_NOFREEZE; + wake_up_process(kapmd_tsk); + +#ifdef CONFIG_PROC_FS + create_proc_info_entry("apm", 0, NULL, apm_get_info); +#endif + + ret = misc_register(&apm_device); + if (ret != 0) { + remove_proc_entry("apm", NULL); + kthread_stop(kapmd_tsk); + } + + return ret; +} + +static void __exit apm_exit(void) +{ + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); + + kthread_stop(kapmd_tsk); +} + +module_init(apm_init); +module_exit(apm_exit); + +MODULE_AUTHOR("Stephen Rothwell"); +MODULE_DESCRIPTION("Advanced Power Management"); +MODULE_LICENSE("GPL"); + +#ifndef MODULE +static int __init apm_setup(char *str) +{ + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("apm=", apm_setup); +#endif + +/** + * apm_queue_event - queue an APM event for kapmd + * @event: APM event + * + * Queue an APM event for kapmd to process and ultimately take the + * appropriate action. Only a subset of events are handled: + * %APM_LOW_BATTERY + * %APM_POWER_STATUS_CHANGE + * %APM_USER_SUSPEND + * %APM_SYS_SUSPEND + * %APM_CRITICAL_SUSPEND + */ +void apm_queue_event(apm_event_t event) +{ + unsigned long flags; + + spin_lock_irqsave(&kapmd_queue_lock, flags); + queue_add_event(&kapmd_queue, event); + spin_unlock_irqrestore(&kapmd_queue_lock, flags); + + wake_up_interruptible(&kapmd_wait); +} +EXPORT_SYMBOL(apm_queue_event); diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 9f8082f..7f60a18 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -187,7 +187,7 @@ static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_ return len; } -static struct file_operations briq_panel_fops = { +static const struct file_operations briq_panel_fops = { .owner = THIS_MODULE, .read = briq_panel_read, .write = briq_panel_write, diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 3ffa080..54df355 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -829,17 +829,18 @@ static unsigned short cy_pci_nboard; static unsigned short cy_isa_nboard; static unsigned short cy_nboard; #ifdef CONFIG_PCI -static unsigned short cy_pci_dev_id[] = { - PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */ - 0 /* end of table */ +static struct pci_device_id cy_pci_dev_id[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) }, /* PCI > 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) }, /* 4Y PCI < 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) }, /* 4Y PCI > 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) }, /* 8Y PCI < 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) }, /* 8Y PCI > 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) }, /* Z PCI < 1Mb */ + { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) }, /* Z PCI > 1Mb */ + { } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); #endif static void cy_start(struct tty_struct *); @@ -4488,7 +4489,6 @@ static void cy_flush_buffer(struct tty_struct *tty) CY_UNLOCK(info, flags); } tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); } /* cy_flush_buffer */ /* @@ -4759,7 +4759,7 @@ static int __init cy_detect_pci(void) for (i = 0; i < NR_CARDS; i++) { /* look for a Cyclades card by vendor and device id */ - while ((device_id = cy_pci_dev_id[dev_index]) != 0) { + while ((device_id = cy_pci_dev_id[dev_index].device) != 0) { if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, device_id, pdev)) == NULL) { dev_index++; /* try next device id */ diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 6dcdceb..85d99e2 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -532,11 +532,13 @@ typedef struct drm_mm_node { int free; unsigned long start; unsigned long size; + struct drm_mm *mm; void *private; } drm_mm_node_t; typedef struct drm_mm { - drm_mm_node_t root_node; + struct list_head fl_entry; + struct list_head ml_entry; } drm_mm_t; /** @@ -843,9 +845,6 @@ extern void drm_mem_init(void); extern int drm_mem_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); -extern void *drm_ioremap(unsigned long offset, unsigned long size, - drm_device_t * dev); -extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev); extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); @@ -1053,33 +1052,18 @@ extern void drm_sysfs_device_remove(struct class_device *class_dev); extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, unsigned long size, unsigned alignment); -extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur); +void drm_mm_put_block(drm_mm_node_t * cur); extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, unsigned alignment, int best_match); extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); extern void drm_mm_takedown(drm_mm_t *mm); +extern int drm_mm_clean(drm_mm_t *mm); +extern unsigned long drm_mm_tail_space(drm_mm_t *mm); +extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size); +extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size); -/* Inline replacements for DRM_IOREMAP macros */ -static __inline__ void drm_core_ioremap(struct drm_map *map, - struct drm_device *dev) -{ - map->handle = drm_ioremap(map->offset, map->size, dev); -} - -#if 0 -static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, - struct drm_device *dev) -{ - map->handle = drm_ioremap_nocache(map->offset, map->size, dev); -} -#endif /* 0 */ - -static __inline__ void drm_core_ioremapfree(struct drm_map *map, - struct drm_device *dev) -{ - if (map->handle && map->size) - drm_ioremapfree(map->handle, map->size, dev); -} +extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev); +extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev); static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned int token) diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 9f65f56..a6828cc 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -79,14 +79,14 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash, if (!use_hashed_handle) { int ret; - hash->key = user_token; + hash->key = user_token >> PAGE_SHIFT; ret = drm_ht_insert_item(&dev->map_hash, hash); if (ret != -EINVAL) return ret; } return drm_ht_just_insert_please(&dev->map_hash, hash, user_token, 32 - PAGE_SHIFT - 3, - PAGE_SHIFT, DRM_MAP_HASH_OFFSET); + 0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT); } /** @@ -178,11 +178,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, } } if (map->type == _DRM_REGISTERS) - map->handle = drm_ioremap(map->offset, map->size, dev); + map->handle = ioremap(map->offset, map->size); break; case _DRM_SHM: - map->handle = vmalloc_32(map->size); + map->handle = vmalloc_user(map->size); DRM_DEBUG("%lu %d %p\n", map->size, drm_order(map->size), map->handle); if (!map->handle) { @@ -238,7 +238,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); if (!list) { if (map->type == _DRM_REGISTERS) - drm_ioremapfree(map->handle, map->size, dev); + iounmap(map->handle); drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; } @@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, ret = drm_map_handle(dev, &list->hash, user_token, 0); if (ret) { if (map->type == _DRM_REGISTERS) - drm_ioremapfree(map->handle, map->size, dev); + iounmap(map->handle); drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(list, sizeof(*list), DRM_MEM_MAPS); mutex_unlock(&dev->struct_mutex); return ret; } - list->user_token = list->hash.key; + list->user_token = list->hash.key << PAGE_SHIFT; mutex_unlock(&dev->struct_mutex); *maplist = list; @@ -347,7 +347,8 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) if (r_list->map == map) { list_del(list); - drm_ht_remove_key(&dev->map_hash, r_list->user_token); + drm_ht_remove_key(&dev->map_hash, + r_list->user_token >> PAGE_SHIFT); drm_free(list, sizeof(*list), DRM_MEM_MAPS); break; } @@ -362,7 +363,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) switch (map->type) { case _DRM_REGISTERS: - drm_ioremapfree(map->handle, map->size, dev); + iounmap(map->handle); /* FALLTHROUGH */ case _DRM_FRAME_BUFFER: if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index a70af0d..f5b9b24 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -371,7 +371,7 @@ void drm_exit(struct drm_driver *driver) EXPORT_SYMBOL(drm_exit); /** File operations structure */ -static struct file_operations drm_stub_fops = { +static const struct file_operations drm_stub_fops = { .owner = THIS_MODULE, .open = drm_stub_open }; diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 5681cae..92a8670 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c @@ -79,28 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) } #if __OS_HAS_AGP -/* - * Find the drm_map that covers the range [offset, offset+size). - */ -static drm_map_t *drm_lookup_map(unsigned long offset, - unsigned long size, drm_device_t * dev) -{ - struct list_head *list; - drm_map_list_t *r_list; - drm_map_t *map; - - list_for_each(list, &dev->maplist->head) { - r_list = (drm_map_list_t *) list; - map = r_list->map; - if (!map) - continue; - if (map->offset <= offset - && (offset + size) <= (map->offset + map->size)) - return map; - } - return NULL; -} - static void *agp_remap(unsigned long offset, unsigned long size, drm_device_t * dev) { @@ -169,13 +147,6 @@ int drm_unbind_agp(DRM_AGP_MEM * handle) } #else /* __OS_HAS_AGP */ - -static inline drm_map_t *drm_lookup_map(unsigned long offset, - unsigned long size, drm_device_t * dev) -{ - return NULL; -} - static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t * dev) { @@ -184,57 +155,28 @@ static inline void *agp_remap(unsigned long offset, unsigned long size, #endif /* agp */ -void *drm_ioremap(unsigned long offset, unsigned long size, - drm_device_t * dev) -{ - if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { - drm_map_t *map = drm_lookup_map(offset, size, dev); - - if (map && map->type == _DRM_AGP) - return agp_remap(offset, size, dev); - } - return ioremap(offset, size); -} -EXPORT_SYMBOL(drm_ioremap); +#endif /* debug_memory */ -#if 0 -void *drm_ioremap_nocache(unsigned long offset, - unsigned long size, drm_device_t * dev) +void drm_core_ioremap(struct drm_map *map, struct drm_device *dev) { - if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { - drm_map_t *map = drm_lookup_map(offset, size, dev); - - if (map && map->type == _DRM_AGP) - return agp_remap(offset, size, dev); - } - return ioremap_nocache(offset, size); + if (drm_core_has_AGP(dev) && + dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) + map->handle = agp_remap(map->offset, map->size, dev); + else + map->handle = ioremap(map->offset, map->size); } -#endif /* 0 */ +EXPORT_SYMBOL(drm_core_ioremap); -void drm_ioremapfree(void *pt, unsigned long size, - drm_device_t * dev) +void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) { - /* - * This is a bit ugly. It would be much cleaner if the DRM API would use separate - * routines for handling mappings in the AGP space. Hopefully this can be done in - * a future revision of the interface... - */ - if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture - && ((unsigned long)pt >= VMALLOC_START - && (unsigned long)pt < VMALLOC_END)) { - unsigned long offset; - drm_map_t *map; - - offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); - map = drm_lookup_map(offset, size, dev); - if (map && map->type == _DRM_AGP) { - vunmap(pt); - return; - } - } - - iounmap(pt); + if (!map->handle || !map->size) + return; + + if (drm_core_has_AGP(dev) && + dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) + vunmap(map->handle); + else + iounmap(map->handle); } -EXPORT_SYMBOL(drm_ioremapfree); +EXPORT_SYMBOL(drm_core_ioremapfree); -#endif /* debug_memory */ diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h index f1b97af..63e425b 100644 --- a/drivers/char/drm/drm_memory.h +++ b/drivers/char/drm/drm_memory.h @@ -56,26 +56,6 @@ # endif #endif -static inline unsigned long drm_follow_page(void *vaddr) -{ - pgd_t *pgd = pgd_offset_k((unsigned long)vaddr); - pud_t *pud = pud_offset(pgd, (unsigned long)vaddr); - pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr); - pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr); - return pte_pfn(*ptep) << PAGE_SHIFT; -} - #else /* __OS_HAS_AGP */ -static inline unsigned long drm_follow_page(void *vaddr) -{ - return 0; -} - #endif - -void *drm_ioremap(unsigned long offset, unsigned long size, - drm_device_t * dev); - -void drm_ioremapfree(void *pt, unsigned long size, - drm_device_t * dev); diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index 74581af..6463271 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h @@ -205,76 +205,6 @@ void drm_free (void *pt, size_t size, int area) { } } -void *drm_ioremap (unsigned long offset, unsigned long size, - drm_device_t * dev) { - void *pt; - - if (!size) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Mapping 0 bytes at 0x%08lx\n", offset); - return NULL; - } - - if (!(pt = drm_ioremap(offset, size, dev))) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; - spin_unlock(&drm_mem_lock); - return NULL; - } - spin_lock(&drm_mem_lock); - ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; - drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; - spin_unlock(&drm_mem_lock); - return pt; -} - -#if 0 -void *drm_ioremap_nocache (unsigned long offset, unsigned long size, - drm_device_t * dev) { - void *pt; - - if (!size) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Mapping 0 bytes at 0x%08lx\n", offset); - return NULL; - } - - if (!(pt = drm_ioremap_nocache(offset, size, dev))) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; - spin_unlock(&drm_mem_lock); - return NULL; - } - spin_lock(&drm_mem_lock); - ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; - drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; - spin_unlock(&drm_mem_lock); - return pt; -} -#endif /* 0 */ - -void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) { - int alloc_count; - int free_count; - - if (!pt) - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Attempt to free NULL pointer\n"); - else - drm_ioremapfree(pt, size, dev); - - spin_lock(&drm_mem_lock); - drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size; - free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count; - alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; - spin_unlock(&drm_mem_lock); - if (free_count > alloc_count) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } -} - #if __OS_HAS_AGP DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c index 617526b..9b46b85 100644 --- a/drivers/char/drm/drm_mm.c +++ b/drivers/char/drm/drm_mm.c @@ -42,36 +42,131 @@ */ #include "drmP.h" +#include <linux/slab.h> + +unsigned long drm_mm_tail_space(drm_mm_t *mm) +{ + struct list_head *tail_node; + drm_mm_node_t *entry; + + tail_node = mm->ml_entry.prev; + entry = list_entry(tail_node, drm_mm_node_t, ml_entry); + if (!entry->free) + return 0; + + return entry->size; +} + +int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size) +{ + struct list_head *tail_node; + drm_mm_node_t *entry; + + tail_node = mm->ml_entry.prev; + entry = list_entry(tail_node, drm_mm_node_t, ml_entry); + if (!entry->free) + return -ENOMEM; + + if (entry->size <= size) + return -ENOMEM; + + entry->size -= size; + return 0; +} + + +static int drm_mm_create_tail_node(drm_mm_t *mm, + unsigned long start, + unsigned long size) +{ + drm_mm_node_t *child; + + child = (drm_mm_node_t *) + drm_alloc(sizeof(*child), DRM_MEM_MM); + if (!child) + return -ENOMEM; + + child->free = 1; + child->size = size; + child->start = start; + child->mm = mm; + + list_add_tail(&child->ml_entry, &mm->ml_entry); + list_add_tail(&child->fl_entry, &mm->fl_entry); + + return 0; +} + + +int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size) +{ + struct list_head *tail_node; + drm_mm_node_t *entry; + + tail_node = mm->ml_entry.prev; + entry = list_entry(tail_node, drm_mm_node_t, ml_entry); + if (!entry->free) { + return drm_mm_create_tail_node(mm, entry->start + entry->size, size); + } + entry->size += size; + return 0; +} + +static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent, + unsigned long size) +{ + drm_mm_node_t *child; + + child = (drm_mm_node_t *) + drm_alloc(sizeof(*child), DRM_MEM_MM); + if (!child) + return NULL; + + INIT_LIST_HEAD(&child->fl_entry); + + child->free = 0; + child->size = size; + child->start = parent->start; + child->mm = parent->mm; + + list_add_tail(&child->ml_entry, &parent->ml_entry); + INIT_LIST_HEAD(&child->fl_entry); + + parent->size -= size; + parent->start += size; + return child; +} + + drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, unsigned long size, unsigned alignment) { + drm_mm_node_t *align_splitoff = NULL; drm_mm_node_t *child; + unsigned tmp = 0; if (alignment) - size += alignment - 1; + tmp = parent->start % alignment; + + if (tmp) { + align_splitoff = drm_mm_split_at_start(parent, alignment - tmp); + if (!align_splitoff) + return NULL; + } if (parent->size == size) { list_del_init(&parent->fl_entry); parent->free = 0; return parent; } else { - child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); - if (!child) - return NULL; - - INIT_LIST_HEAD(&child->ml_entry); - INIT_LIST_HEAD(&child->fl_entry); + child = drm_mm_split_at_start(parent, size); + } - child->free = 0; - child->size = size; - child->start = parent->start; + if (align_splitoff) + drm_mm_put_block(align_splitoff); - list_add_tail(&child->ml_entry, &parent->ml_entry); - parent->size -= size; - parent->start += size; - } return child; } @@ -80,12 +175,12 @@ drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, * Otherwise add to the free stack. */ -void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) +void drm_mm_put_block(drm_mm_node_t * cur) { - drm_mm_node_t *list_root = &mm->root_node; + drm_mm_t *mm = cur->mm; struct list_head *cur_head = &cur->ml_entry; - struct list_head *root_head = &list_root->ml_entry; + struct list_head *root_head = &mm->ml_entry; drm_mm_node_t *prev_node = NULL; drm_mm_node_t *next_node; @@ -116,7 +211,7 @@ void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) } if (!merged) { cur->free = 1; - list_add(&cur->fl_entry, &list_root->fl_entry); + list_add(&cur->fl_entry, &mm->fl_entry); } else { list_del(&cur->ml_entry); drm_free(cur, sizeof(*cur), DRM_MEM_MM); @@ -128,20 +223,30 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, unsigned alignment, int best_match) { struct list_head *list; - const struct list_head *free_stack = &mm->root_node.fl_entry; + const struct list_head *free_stack = &mm->fl_entry; drm_mm_node_t *entry; drm_mm_node_t *best; unsigned long best_size; + unsigned wasted; best = NULL; best_size = ~0UL; - if (alignment) - size += alignment - 1; - list_for_each(list, free_stack) { entry = list_entry(list, drm_mm_node_t, fl_entry); - if (entry->size >= size) { + wasted = 0; + + if (entry->size < size) + continue; + + if (alignment) { + register unsigned tmp = entry->start % alignment; + if (tmp) + wasted += alignment - tmp; + } + + + if (entry->size >= size + wasted) { if (!best_match) return entry; if (size < best_size) { @@ -154,40 +259,32 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, return best; } -int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) +int drm_mm_clean(drm_mm_t * mm) { - drm_mm_node_t *child; - - INIT_LIST_HEAD(&mm->root_node.ml_entry); - INIT_LIST_HEAD(&mm->root_node.fl_entry); - child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); - if (!child) - return -ENOMEM; - - INIT_LIST_HEAD(&child->ml_entry); - INIT_LIST_HEAD(&child->fl_entry); + struct list_head *head = &mm->ml_entry; - child->start = start; - child->size = size; - child->free = 1; + return (head->next->next == head); +} - list_add(&child->fl_entry, &mm->root_node.fl_entry); - list_add(&child->ml_entry, &mm->root_node.ml_entry); +int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) +{ + INIT_LIST_HEAD(&mm->ml_entry); + INIT_LIST_HEAD(&mm->fl_entry); - return 0; + return drm_mm_create_tail_node(mm, start, size); } EXPORT_SYMBOL(drm_mm_init); void drm_mm_takedown(drm_mm_t * mm) { - struct list_head *bnode = mm->root_node.fl_entry.next; + struct list_head *bnode = mm->fl_entry.next; drm_mm_node_t *entry; entry = list_entry(bnode, drm_mm_node_t, fl_entry); - if (entry->ml_entry.next != &mm->root_node.ml_entry || - entry->fl_entry.next != &mm->root_node.fl_entry) { + if (entry->ml_entry.next != &mm->ml_entry || + entry->fl_entry.next != &mm->fl_entry) { DRM_ERROR("Memory manager not clean. Delaying takedown\n"); return; } diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 09398d5..ad54b84 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -226,12 +226,14 @@ {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ - {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ {0, 0, 0} #define i810_PCI_IDS \ diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 62d5fe1..7fd0da7 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c @@ -500,7 +500,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, for (pt = dev->vmalist; pt; pt = pt->next) { if (!(vma = pt->vma)) continue; - DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", + DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", pt->pid, vma->vm_start, vma->vm_end, @@ -510,7 +510,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, vma->vm_flags & VM_MAYSHARE ? 's' : 'p', vma->vm_flags & VM_LOCKED ? 'l' : '-', vma->vm_flags & VM_IO ? 'i' : '-', - vma->vm_pgoff << PAGE_SHIFT); + vma->vm_pgoff); #if defined(__i386__) pgprot = pgprot_val(vma->vm_page_prot); diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c index 19c81d2..e15db6d 100644 --- a/drivers/char/drm/drm_sman.c +++ b/drivers/char/drm/drm_sman.c @@ -101,10 +101,9 @@ static void *drm_sman_mm_allocate(void *private, unsigned long size, static void drm_sman_mm_free(void *private, void *ref) { - drm_mm_t *mm = (drm_mm_t *) private; drm_mm_node_t *node = (drm_mm_node_t *) ref; - drm_mm_put_block(mm, node); + drm_mm_put_block(node); } static void drm_sman_mm_destroy(void *private) diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index b9cfc07..54a6328 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -70,7 +70,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, if (!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; - if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) + if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) goto vm_nopage_error; r_list = drm_hash_entry(hash, drm_map_list_t, hash); @@ -227,7 +227,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) map->size); DRM_DEBUG("mtrr_del = %d\n", retcode); } - drm_ioremapfree(map->handle, map->size, dev); + iounmap(map->handle); break; case _DRM_SHM: vfree(map->handle); @@ -463,8 +463,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) lock_kernel(); dev = priv->head->dev; dma = dev->dma; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); + DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff); /* Length must match exact page count */ if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { @@ -537,8 +537,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) unsigned long offset = 0; drm_hash_item_t *hash; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); + DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff); if (!priv->authenticated) return -EACCES; @@ -547,7 +547,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) * the AGP mapped at physical address 0 * --BenH. */ - if (!(vma->vm_pgoff << PAGE_SHIFT) + if (!vma->vm_pgoff #if __OS_HAS_AGP && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) @@ -555,7 +555,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) ) return drm_mmap_dma(filp, vma); - if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) { + if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) { DRM_ERROR("Could not find map\n"); return -EINVAL; } diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index fa2de70..603d17f 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -112,7 +112,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) return 0; } -static struct file_operations i810_buffer_fops = { +static const struct file_operations i810_buffer_fops = { .open = drm_open, .release = drm_release, .ioctl = drm_ioctl, @@ -219,8 +219,7 @@ static int i810_dma_cleanup(drm_device_t * dev) (drm_i810_private_t *) dev->dev_private; if (dev_priv->ring.virtual_start) { - drm_ioremapfree((void *)dev_priv->ring.virtual_start, - dev_priv->ring.Size, dev); + drm_core_ioremapfree(&dev_priv->ring.map, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -236,9 +235,9 @@ static int i810_dma_cleanup(drm_device_t * dev) for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[i]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; + if (buf_priv->kernel_virtual && buf->total) - drm_ioremapfree(buf_priv->kernel_virtual, - buf->total, dev); + drm_core_ioremapfree(&buf_priv->map, dev); } } return 0; @@ -311,8 +310,15 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv) *buf_priv->in_use = I810_BUF_FREE; - buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, - buf->total, dev); + buf_priv->map.offset = buf->bus_address; + buf_priv->map.size = buf->total; + buf_priv->map.type = _DRM_AGP; + buf_priv->map.flags = 0; + buf_priv->map.mtrr = 0; + + drm_core_ioremap(&buf_priv->map, dev); + buf_priv->kernel_virtual = buf_priv->map.handle; + } return 0; } @@ -363,18 +369,24 @@ static int i810_dma_initialize(drm_device_t * dev, dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; - dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + - init->ring_start, - init->ring_size, dev); + dev_priv->ring.map.offset = dev->agp->base + init->ring_start; + dev_priv->ring.map.size = init->ring_size; + dev_priv->ring.map.type = _DRM_AGP; + dev_priv->ring.map.flags = 0; + dev_priv->ring.map.mtrr = 0; - if (dev_priv->ring.virtual_start == NULL) { + drm_core_ioremap(&dev_priv->ring.map, dev); + + if (dev_priv->ring.map.handle == NULL) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return -ENOMEM; + return DRM_ERR(ENOMEM); } + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; dev_priv->w = init->w; diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index e8cf3ff6..e6df49f4 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h @@ -61,6 +61,7 @@ typedef struct drm_i810_buf_priv { int currently_mapped; void *virtual; void *kernel_virtual; + drm_local_map_t map; } drm_i810_buf_priv_t; typedef struct _drm_i810_ring_buffer { @@ -72,6 +73,7 @@ typedef struct _drm_i810_ring_buffer { int head; int tail; int space; + drm_local_map_t map; } drm_i810_ring_buffer_t; typedef struct drm_i810_private { diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 4f0e574..3314a9f 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -114,7 +114,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) return 0; } -static struct file_operations i830_buffer_fops = { +static const struct file_operations i830_buffer_fops = { .open = drm_open, .release = drm_release, .ioctl = drm_ioctl, @@ -223,8 +223,7 @@ static int i830_dma_cleanup(drm_device_t * dev) (drm_i830_private_t *) dev->dev_private; if (dev_priv->ring.virtual_start) { - drm_ioremapfree((void *)dev_priv->ring.virtual_start, - dev_priv->ring.Size, dev); + drm_core_ioremapfree(&dev_priv->ring.map, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -242,8 +241,7 @@ static int i830_dma_cleanup(drm_device_t * dev) drm_buf_t *buf = dma->buflist[i]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; if (buf_priv->kernel_virtual && buf->total) - drm_ioremapfree(buf_priv->kernel_virtual, - buf->total, dev); + drm_core_ioremapfree(&buf_priv->map, dev); } } return 0; @@ -320,8 +318,14 @@ static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv) *buf_priv->in_use = I830_BUF_FREE; - buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, - buf->total, dev); + buf_priv->map.offset = buf->bus_address; + buf_priv->map.size = buf->total; + buf_priv->map.type = _DRM_AGP; + buf_priv->map.flags = 0; + buf_priv->map.mtrr = 0; + + drm_core_ioremap(&buf_priv->map, dev); + buf_priv->kernel_virtual = buf_priv->map.handle; } return 0; } @@ -373,18 +377,24 @@ static int i830_dma_initialize(drm_device_t * dev, dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; - dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + - init->ring_start, - init->ring_size, dev); + dev_priv->ring.map.offset = dev->agp->base + init->ring_start; + dev_priv->ring.map.size = init->ring_size; + dev_priv->ring.map.type = _DRM_AGP; + dev_priv->ring.map.flags = 0; + dev_priv->ring.map.mtrr = 0; + + drm_core_ioremap(&dev_priv->ring.map, dev); - if (dev_priv->ring.virtual_start == NULL) { + if (dev_priv->ring.map.handle == NULL) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return -ENOMEM; + return DRM_ERR(ENOMEM); } + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; dev_priv->w = init->w; diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index 85bc5be..e91f94a 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h @@ -68,6 +68,7 @@ typedef struct drm_i830_buf_priv { int currently_mapped; void __user *virtual; void *kernel_virtual; + drm_local_map_t map; } drm_i830_buf_priv_t; typedef struct _drm_i830_ring_buffer { @@ -79,6 +80,7 @@ typedef struct _drm_i830_ring_buffer { int head; int tail; int space; + drm_local_map_t map; } drm_i830_ring_buffer_t; typedef struct drm_i830_private { diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index a691ae7..c0539c6 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c @@ -190,6 +190,11 @@ static int via_initialize(drm_device_t * dev, return DRM_ERR(EFAULT); } + if (dev_priv->chipset == VIA_DX9_0) { + DRM_ERROR("AGP DMA is not supported on this chip\n"); + return DRM_ERR(EINVAL); + } + dev_priv->ring.map.offset = dev->agp->base + init->offset; dev_priv->ring.map.size = init->size; dev_priv->ring.map.type = 0; @@ -480,6 +485,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv, VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); + VIA_READ(VIA_REG_TRANSPACE); } } return paused; @@ -557,8 +563,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); - + DRM_WRITEMEMORYBARRIER(); VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); + VIA_READ(VIA_REG_TRANSPACE); } static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 806f9ce..2881a06 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -218,7 +218,9 @@ via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine) VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); + DRM_WRITEMEMORYBARRIER(); VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); + VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04); } /* @@ -374,10 +376,8 @@ via_dmablit_handler(drm_device_t *dev, int engine, int from_irq) blitq->cur = cur; blitq->num_outstanding--; blitq->end = jiffies + DRM_HZ; - if (!timer_pending(&blitq->poll_timer)) { - blitq->poll_timer.expires = jiffies+1; - add_timer(&blitq->poll_timer); - } + if (!timer_pending(&blitq->poll_timer)) + mod_timer(&blitq->poll_timer, jiffies + 1); } else { if (timer_pending(&blitq->poll_timer)) { del_timer(&blitq->poll_timer); @@ -476,8 +476,7 @@ via_dmablit_timer(unsigned long data) via_dmablit_handler(dev, engine, 0); if (!timer_pending(&blitq->poll_timer)) { - blitq->poll_timer.expires = jiffies+1; - add_timer(&blitq->poll_timer); + mod_timer(&blitq->poll_timer, jiffies + 1); /* * Rerun handler to delete timer if engines are off, and @@ -572,9 +571,8 @@ via_init_dmablit(drm_device_t *dev) } DRM_INIT_WAITQUEUE(&blitq->busy_queue); INIT_WORK(&blitq->wq, via_dmablit_workqueue); - init_timer(&blitq->poll_timer); - blitq->poll_timer.function = &via_dmablit_timer; - blitq->poll_timer.data = (unsigned long) blitq; + setup_timer(&blitq->poll_timer, via_dmablit_timer, + (unsigned long)blitq); } } diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index d21b5b7..8b8778d 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h @@ -29,10 +29,10 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome / Pro" -#define DRIVER_DATE "20060529" +#define DRIVER_DATE "20061227" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 10 +#define DRIVER_MINOR 11 #define DRIVER_PATCHLEVEL 0 #include "via_verifier.h" @@ -79,7 +79,7 @@ typedef struct drm_via_private { char pci_buf[VIA_PCI_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; uint32_t num_fire_offsets; - int pro_group_a; + int chipset; drm_via_irq_t via_irqs[VIA_NUM_IRQS]; unsigned num_irqs; maskarray_t *irq_masks; @@ -96,8 +96,9 @@ typedef struct drm_via_private { } drm_via_private_t; enum via_family { - VIA_OTHER = 0, - VIA_PRO_GROUP_A, + VIA_OTHER = 0, /* Baseline */ + VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ + VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */ }; /* VIA MMIO register access */ diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index c33d068..1ac5941 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c @@ -258,12 +258,16 @@ void via_driver_irq_preinstall(drm_device_t * dev) dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; - dev_priv->irq_masks = (dev_priv->pro_group_a) ? - via_pro_group_a_irqs : via_unichrome_irqs; - dev_priv->num_irqs = (dev_priv->pro_group_a) ? - via_num_pro_group_a : via_num_unichrome; - dev_priv->irq_map = (dev_priv->pro_group_a) ? - via_irqmap_pro_group_a : via_irqmap_unichrome; + if (dev_priv->chipset == VIA_PRO_GROUP_A || + dev_priv->chipset == VIA_DX9_0) { + dev_priv->irq_masks = via_pro_group_a_irqs; + dev_priv->num_irqs = via_num_pro_group_a; + dev_priv->irq_map = via_irqmap_pro_group_a; + } else { + dev_priv->irq_masks = via_unichrome_irqs; + dev_priv->num_irqs = via_num_unichrome; + dev_priv->irq_map = via_irqmap_unichrome; + } for (i = 0; i < dev_priv->num_irqs; ++i) { atomic_set(&cur_irq->irq_received, 0); diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c index 782011e..4e3fc07 100644 --- a/drivers/char/drm/via_map.c +++ b/drivers/char/drm/via_map.c @@ -106,8 +106,7 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset) dev->dev_private = (void *)dev_priv; - if (chipset == VIA_PRO_GROUP_A) - dev_priv->pro_group_a = 1; + dev_priv->chipset = chipset; ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); if (ret) { diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c index 70c897c..2e7e080 100644 --- a/drivers/char/drm/via_verifier.c +++ b/drivers/char/drm/via_verifier.c @@ -306,6 +306,7 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) unsigned long lo = ~0, hi = 0, tmp; uint32_t *addr, *pitch, *height, tex; unsigned i; + int npot; if (end > 9) end = 9; @@ -316,12 +317,15 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) &(cur_seq->t_addr[tex = cur_seq->texture][start]); pitch = &(cur_seq->pitch[tex][start]); height = &(cur_seq->height[tex][start]); - + npot = cur_seq->tex_npot[tex]; for (i = start; i <= end; ++i) { tmp = *addr++; if (tmp < lo) lo = tmp; - tmp += (*height++ << *pitch++); + if (i == 0 && npot) + tmp += (*height++ * *pitch++); + else + tmp += (*height++ << *pitch++); if (tmp > hi) hi = tmp; } @@ -443,13 +447,21 @@ investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq) return 0; case check_texture_addr3: cur_seq->unfinished = tex_address; - tmp = ((cmd >> 24) - 0x2B); - cur_seq->pitch[cur_seq->texture][tmp] = - (cmd & 0x00F00000) >> 20; - if (!tmp && (cmd & 0x000FFFFF)) { - DRM_ERROR - ("Unimplemented texture level 0 pitch mode.\n"); - return 2; + tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit); + if (tmp == 0 && + (cmd & HC_HTXnEnPit_MASK)) { + cur_seq->pitch[cur_seq->texture][tmp] = + (cmd & HC_HTXnLnPit_MASK); + cur_seq->tex_npot[cur_seq->texture] = 1; + } else { + cur_seq->pitch[cur_seq->texture][tmp] = + (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT; + cur_seq->tex_npot[cur_seq->texture] = 0; + if (cmd & 0x000FFFFF) { + DRM_ERROR + ("Unimplemented texture level 0 pitch mode.\n"); + return 2; + } } return 0; case check_texture_addr4: @@ -961,7 +973,13 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, uint32_t cmd; const uint32_t *buf_end = buf + (size >> 2); verifier_state_t state = state_command; - int pro_group_a = dev_priv->pro_group_a; + int cme_video; + int supported_3d; + + cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A || + dev_priv->chipset == VIA_DX9_0); + + supported_3d = dev_priv->chipset != VIA_DX9_0; hc_state->dev = dev; hc_state->unfinished = no_sequence; @@ -986,17 +1004,21 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, state = via_check_vheader6(&buf, buf_end); break; case state_command: - if (HALCYON_HEADER2 == (cmd = *buf)) + if ((HALCYON_HEADER2 == (cmd = *buf)) && + supported_3d) state = state_header2; else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) state = state_header1; - else if (pro_group_a + else if (cme_video && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) state = state_vheader5; - else if (pro_group_a + else if (cme_video && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) state = state_vheader6; - else { + else if ((cmd == HALCYON_HEADER2) && !supported_3d) { + DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n"); + state = state_error; + } else { DRM_ERROR ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", cmd); diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h index 256590f..b77f59d 100644 --- a/drivers/char/drm/via_verifier.h +++ b/drivers/char/drm/via_verifier.h @@ -43,6 +43,7 @@ typedef struct { uint32_t tex_level_lo[2]; uint32_t tex_level_hi[2]; uint32_t tex_palette_size[2]; + uint32_t tex_npot[2]; drm_via_sequence_t unfinished; int agp_texture; int multitex; diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index bcdb107..fada6dd 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c @@ -120,7 +120,6 @@ get_rtc_time(struct rtc_time *rtc_tm) unsigned long flags; local_irq_save(flags); - local_irq_disable(); rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); @@ -219,7 +218,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, BIN_TO_BCD(yrs); local_irq_save(flags); - local_irq_disable(); CMOS_WRITE(yrs, RTC_YEAR); CMOS_WRITE(mon, RTC_MONTH); CMOS_WRITE(day, RTC_DAY_OF_MONTH); diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index d4005e9..d8dbdb9 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -72,6 +72,7 @@ #define TRACE_RET ((void) 0) #endif /* TRACING */ +static void dtlk_timer_tick(unsigned long data); static int dtlk_major; static int dtlk_port_lpc; @@ -81,7 +82,7 @@ static int dtlk_has_indexing; static unsigned int dtlk_portlist[] = {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0}; static wait_queue_head_t dtlk_process_list; -static struct timer_list dtlk_timer; +static DEFINE_TIMER(dtlk_timer, dtlk_timer_tick, 0, 0); /* prototypes for file_operations struct */ static ssize_t dtlk_read(struct file *, char __user *, @@ -117,7 +118,6 @@ static char dtlk_write_tts(char); /* static void dtlk_handle_error(char, char, unsigned int); */ -static void dtlk_timer_tick(unsigned long data); static ssize_t dtlk_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) @@ -318,7 +318,7 @@ static int dtlk_release(struct inode *inode, struct file *file) } TRACE_RET; - del_timer(&dtlk_timer); + del_timer_sync(&dtlk_timer); return 0; } @@ -336,8 +336,6 @@ static int __init dtlk_init(void) if (dtlk_dev_probe() == 0) printk(", MAJOR %d\n", dtlk_major); - init_timer(&dtlk_timer); - dtlk_timer.function = dtlk_timer_tick; init_waitqueue_head(&dtlk_process_list); return 0; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index a0f822c..88fc24f 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -844,7 +844,6 @@ static void pc_flush_buffer(struct tty_struct *tty) fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); memoff(ch); spin_unlock_irqrestore(&epca_lock, flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } /* End pc_flush_buffer */ @@ -1795,7 +1794,6 @@ static void doevent(int crd) { /* Begin if LOWWAIT */ ch->statusflags &= ~LOWWAIT; tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); } /* End if LOWWAIT */ } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */ /* This event is generated by setup_empty_event */ @@ -1803,7 +1801,6 @@ static void doevent(int crd) if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */ ch->statusflags &= ~EMPTYWAIT; tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); } /* End if EMPTYWAIT */ } /* End EMPTYTX_IND */ } /* End if valid tty */ diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 43ff598..2398e86 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -117,7 +117,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, return 0; } -struct file_operations nvram_fops = { +const struct file_operations nvram_fops = { .owner = THIS_MODULE, .llseek = nvram_llseek, .read = read_nvram, diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index e769811..337bbcd 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -382,7 +382,6 @@ void gs_flush_buffer(struct tty_struct *tty) port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; spin_unlock_irqrestore (&port->driver_lock, flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); func_exit (); } diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c new file mode 100644 index 0000000..6f019f1 --- /dev/null +++ b/drivers/char/hvc_beat.c @@ -0,0 +1,134 @@ +/* + * Beat hypervisor console driver + * + * (C) Copyright 2006 TOSHIBA CORPORATION + * + * This code is based on drivers/char/hvc_rtas.c: + * (C) Copyright IBM Corporation 2001-2005 + * (C) Copyright Red Hat, Inc. 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/console.h> +#include <asm/prom.h> +#include <asm/hvconsole.h> +#include <asm/firmware.h> + +#include "hvc_console.h" + +extern int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *); +extern int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t); + +struct hvc_struct *hvc_beat_dev = NULL; + +/* bug: only one queue is available regardless of vtermno */ +static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt) +{ + static unsigned char q[sizeof(unsigned long) * 2] + __attribute__((aligned(sizeof(unsigned long)))); + static int qlen = 0; + unsigned long got; + +again: + if (qlen) { + if (qlen > cnt) { + memcpy(buf, q, cnt); + qlen -= cnt; + memmove(q + cnt, q, qlen); + return cnt; + } else { /* qlen <= cnt */ + int r; + + memcpy(buf, q, qlen); + r = qlen; + qlen = 0; + return r; + } + } + if (beat_get_term_char(vtermno, &got, + ((unsigned long *)q), ((unsigned long *)q) + 1) == 0) { + qlen = got; + goto again; + } + return 0; +} + +static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) +{ + unsigned long kb[2]; + int rest, nlen; + + for (rest = cnt; rest > 0; rest -= nlen) { + nlen = (rest > 16) ? 16 : rest; + memcpy(kb, buf, nlen); + beat_put_term_char(vtermno, rest, kb[0], kb[1]); + rest -= nlen; + } + return cnt; +} + +static struct hv_ops hvc_beat_get_put_ops = { + .get_chars = hvc_beat_get_chars, + .put_chars = hvc_beat_put_chars, +}; + +static int hvc_beat_useit = 1; + +static int hvc_beat_config(char *p) +{ + hvc_beat_useit = simple_strtoul(p, NULL, 0); + return 0; +} + +static int hvc_beat_console_init(void) +{ + if (hvc_beat_useit && machine_is_compatible("Beat")) { + hvc_instantiate(0, 0, &hvc_beat_get_put_ops); + } + return 0; +} + +/* temp */ +static int hvc_beat_init(void) +{ + struct hvc_struct *hp; + + if (!firmware_has_feature(FW_FEATURE_BEAT)) + return -ENODEV; + + hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16); + if (IS_ERR(hp)) + return PTR_ERR(hp); + hvc_beat_dev = hp; + return 0; +} + +static void __exit hvc_beat_exit(void) +{ + if (hvc_beat_dev) + hvc_remove(hvc_beat_dev); +} + +module_init(hvc_beat_init); +module_exit(hvc_beat_exit); + +__setup("hvc_beat=", hvc_beat_config); + +console_initcall(hvc_beat_console_init); diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index f22e78e..cc1046e 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -96,49 +96,49 @@ */ static const struct pci_device_id pci_tbl[] = { /* AA - { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ - { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */ + { PCI_DEVICE(0x8086, 0x2418) }, */ + { PCI_DEVICE(0x8086, 0x2410) }, /* AA */ /* AB - { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ - { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */ + { PCI_DEVICE(0x8086, 0x2428) }, */ + { PCI_DEVICE(0x8086, 0x2420) }, /* AB */ /* ?? - { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { PCI_DEVICE(0x8086, 0x2430) }, */ /* BAM, CAM, DBM, FBM, GxM - { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ - { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */ - { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */ - { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */ - { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */ - { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */ - { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */ + { PCI_DEVICE(0x8086, 0x2448) }, */ + { PCI_DEVICE(0x8086, 0x244c) }, /* BAM */ + { PCI_DEVICE(0x8086, 0x248c) }, /* CAM */ + { PCI_DEVICE(0x8086, 0x24cc) }, /* DBM */ + { PCI_DEVICE(0x8086, 0x2641) }, /* FBM */ + { PCI_DEVICE(0x8086, 0x27b9) }, /* GxM */ + { PCI_DEVICE(0x8086, 0x27bd) }, /* GxM DH */ /* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx - { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ - { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */ - { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */ - { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */ - { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */ - { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */ - { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */ - { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ - { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */ + { PCI_DEVICE(0x8086, 0x244e) }, */ + { PCI_DEVICE(0x8086, 0x2440) }, /* BA */ + { PCI_DEVICE(0x8086, 0x2480) }, /* CA */ + { PCI_DEVICE(0x8086, 0x24c0) }, /* DB */ + { PCI_DEVICE(0x8086, 0x24d0) }, /* Ex */ + { PCI_DEVICE(0x8086, 0x25a1) }, /* 6300 */ + { PCI_DEVICE(0x8086, 0x2640) }, /* Fx */ + { PCI_DEVICE(0x8086, 0x2670) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2671) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2672) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2673) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2674) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2675) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2676) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2677) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2678) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x2679) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x267a) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x267b) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x267c) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x267d) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x267e) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x267f) }, /* 631x/632x */ + { PCI_DEVICE(0x8086, 0x27b8) }, /* Gx */ /* E - { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ - { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E */ + { PCI_DEVICE(0x8086, 0x245e) }, */ + { PCI_DEVICE(0x8086, 0x2450) }, /* E */ { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 7804576..f86fa0c 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c @@ -80,7 +80,7 @@ static int i2RetryFlushOutput(i2ChanStrPtr); // Not a documented part of the library routines (careful...) but the Diagnostic // i2diag.c finds them useful to help the throughput in certain limited // single-threaded operations. -static void iiSendPendingMail(i2eBordStrPtr); +static inline void iiSendPendingMail(i2eBordStrPtr); static void serviceOutgoingFifo(i2eBordStrPtr); // Functions defined in ip2.c as part of interrupt handling @@ -150,6 +150,13 @@ i2Validate ( i2ChanStrPtr pCh ) == (CHANNEL_MAGIC | CHANNEL_SUPPORT)); } +static void iiSendPendingMail_t(unsigned long data) +{ + i2eBordStrPtr pB = (i2eBordStrPtr)data; + + iiSendPendingMail(pB); +} + //****************************************************************************** // Function: iiSendPendingMail(pB) // Parameters: Pointer to a board structure @@ -184,12 +191,9 @@ iiSendPendingMail(i2eBordStrPtr pB) /\/\|=mhw=|\/\/ */ if( ++pB->SendPendingRetry < 16 ) { - - init_timer( &(pB->SendPendingTimer) ); - pB->SendPendingTimer.expires = jiffies + 1; - pB->SendPendingTimer.function = (void*)(unsigned long)iiSendPendingMail; - pB->SendPendingTimer.data = (unsigned long)pB; - add_timer( &(pB->SendPendingTimer) ); + setup_timer(&pB->SendPendingTimer, + iiSendPendingMail_t, (unsigned long)pB); + mod_timer(&pB->SendPendingTimer, jiffies + 1); } else { printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); } @@ -1265,8 +1269,10 @@ i2RetryFlushOutput(i2ChanStrPtr pCh) // soon as all the data is completely sent. //****************************************************************************** static void -i2DrainWakeup(i2ChanStrPtr pCh) +i2DrainWakeup(unsigned long d) { + i2ChanStrPtr pCh = (i2ChanStrPtr)d; + ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); pCh->BookmarkTimer.expires = 0; @@ -1292,14 +1298,12 @@ i2DrainOutput(i2ChanStrPtr pCh, int timeout) } if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { // One per customer (channel) - init_timer( &(pCh->BookmarkTimer) ); - pCh->BookmarkTimer.expires = jiffies + timeout; - pCh->BookmarkTimer.function = (void*)(unsigned long)i2DrainWakeup; - pCh->BookmarkTimer.data = (unsigned long)pCh; + setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, + (unsigned long)pCh); ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); - add_timer( &(pCh->BookmarkTimer) ); + mod_timer(&pCh->BookmarkTimer, jiffies + timeout); } i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); @@ -1373,15 +1377,7 @@ ip2_owake( PTTY tp) ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, (1 << TTY_DO_WRITE_WAKEUP) ); - wake_up_interruptible ( &tp->write_wait ); - if ( ( tp->flags & (1 << TTY_DO_WRITE_WAKEUP) ) - && tp->ldisc.write_wakeup ) - { - (tp->ldisc.write_wakeup) ( tp ); - - ip2trace (CHANN, ITRC_SICMD, 11, 0 ); - - } + tty_wakeup(tp); } static inline void diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 7c70310..83c7258 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -1271,8 +1271,8 @@ static void do_input(struct work_struct *work) // code duplicated from n_tty (ldisc) static inline void isig(int sig, struct tty_struct *tty, int flush) { - if (tty->pgrp > 0) - kill_pg(tty->pgrp, sig, 1); + if (tty->pgrp) + kill_pgrp(tty->pgrp, sig, 1); if (flush || !L_NOFLSH(tty)) { if ( tty->ldisc.flush_buffer ) tty->ldisc.flush_buffer(tty); diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 53582b5..3aff5e9 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -406,13 +406,14 @@ static void clean_up_interface_data(ipmi_smi_t intf) free_smi_msg_list(&intf->waiting_msgs); free_recv_msg_list(&intf->waiting_events); - /* Wholesale remove all the entries from the list in the - * interface and wait for RCU to know that none are in use. */ + /* + * Wholesale remove all the entries from the list in the + * interface and wait for RCU to know that none are in use. + */ mutex_lock(&intf->cmd_rcvrs_mutex); - list_add_rcu(&list, &intf->cmd_rcvrs); - list_del_rcu(&intf->cmd_rcvrs); + INIT_LIST_HEAD(&list); + list_splice_init_rcu(&intf->cmd_rcvrs, &list, synchronize_rcu); mutex_unlock(&intf->cmd_rcvrs_mutex); - synchronize_rcu(); list_for_each_entry_safe(rcvr, rcvr2, &list, link) kfree(rcvr); @@ -451,7 +452,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) mutex_lock(&ipmi_interfaces_mutex); /* Build a list of things to deliver. */ - list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + list_for_each_entry(intf, &ipmi_interfaces, link) { if (intf->intf_num == -1) continue; e = kmalloc(sizeof(*e), GFP_KERNEL); @@ -1886,7 +1887,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, kfree(entry); rv = -ENOMEM; } else { - file->nlink = 1; file->data = data; file->read_proc = read_proc; file->write_proc = write_proc; @@ -2760,9 +2760,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, synchronize_rcu(); kref_put(&intf->refcount, intf_free); } else { - /* After this point the interface is legal to use. */ + /* + * Keep memory order straight for RCU readers. Make + * sure everything else is committed to memory before + * setting intf_num to mark the interface valid. + */ + smp_wmb(); intf->intf_num = i; mutex_unlock(&ipmi_interfaces_mutex); + /* After this point the interface is legal to use. */ call_smi_watchers(i, intf->si_dev); mutex_unlock(&smi_watchers_mutex); } @@ -3923,6 +3929,14 @@ static void send_panic_events(char *str) /* Interface was not ready yet. */ continue; + /* + * intf_num is used as an marker to tell if the + * interface is valid. Thus we need a read barrier to + * make sure data fetched before checking intf_num + * won't be used. + */ + smp_rmb(); + /* First job here is to figure out where to send the OEM events. There's no way in IPMI to send OEM events using an event send command, so we have to diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f1afd26..a7b33d2 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1802,7 +1802,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) return -ENODEV; } - if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) addr_space = IPMI_MEM_ADDR_SPACE; else addr_space = IPMI_IO_ADDR_SPACE; @@ -1848,19 +1848,19 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) info->irq_setup = NULL; } - if (spmi->addr.register_bit_width) { + if (spmi->addr.bit_width) { /* A (hopefully) properly formed register bit width. */ - info->io.regspacing = spmi->addr.register_bit_width / 8; + info->io.regspacing = spmi->addr.bit_width / 8; } else { info->io.regspacing = DEFAULT_REGSPACING; } info->io.regsize = info->io.regspacing; - info->io.regshift = spmi->addr.register_bit_offset; + info->io.regshift = spmi->addr.bit_offset; - if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { info->io_setup = mem_setup; info->io.addr_type = IPMI_IO_ADDR_SPACE; - } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { + } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { info->io_setup = port_setup; info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else { @@ -1888,10 +1888,8 @@ static __devinit void acpi_find_bmc(void) return; for (i = 0; ; i++) { - status = acpi_get_firmware_table("SPMI", i+1, - ACPI_LOGICAL_ADDRESSING, - (struct acpi_table_header **) - &spmi); + status = acpi_get_table(ACPI_SIG_SPMI, i+1, + (struct acpi_table_header **)&spmi); if (status != AE_OK) return; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 01084ab..43ab9ed 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -183,7 +183,7 @@ static DEFINE_TIMER(tx, isicom_tx, 0, 0); /* baud index mappings from linux defns to isi */ static signed char linuxb_to_isib[] = { - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21 }; struct isi_board { @@ -213,8 +213,6 @@ struct isi_port { struct tty_struct * tty; wait_queue_head_t close_wait; wait_queue_head_t open_wait; - struct work_struct hangup_tq; - struct work_struct bh_tqueue; unsigned char * xmit_buf; int xmit_head; int xmit_tail; @@ -510,7 +508,7 @@ static void isicom_tx(unsigned long _data) if (port->xmit_cnt <= 0) port->status &= ~ISI_TXOK; if (port->xmit_cnt <= WAKEUP_CHARS) - schedule_work(&port->bh_tqueue); + tty_wakeup(tty); unlock_card(&isi_card[card]); } @@ -524,21 +522,6 @@ sched_again: mod_timer(&tx, jiffies + msecs_to_jiffies(10)); } -/* Interrupt handlers */ - - -static void isicom_bottomhalf(struct work_struct *work) -{ - struct isi_port *port = container_of(work, struct isi_port, bh_tqueue); - struct tty_struct *tty = port->tty; - - if (!tty) - return; - - tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); -} - /* * Main interrupt handler routine */ @@ -557,6 +540,11 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) return IRQ_NONE; base = card->base; + + /* did the card interrupt us? */ + if (!(inw(base + 0x0e) & 0x02)) + return IRQ_NONE; + spin_lock(&card->card_lock); /* @@ -581,6 +569,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) port = card->ports + channel; if (!(port->flags & ASYNC_INITIALIZED)) { outw(0x0000, base+0x04); /* enable interrupts */ + spin_unlock(&card->card_lock); return IRQ_HANDLED; } @@ -609,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) pr_dbg("interrupt: DCD->low.\n" ); port->status &= ~ISI_DCD; - schedule_work(&port->hangup_tq); + tty_hangup(tty); } } else if (header & ISI_DCD) { /* Carrier has been detected */ @@ -631,7 +620,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) /* start tx ing */ port->status |= (ISI_TXOK | ISI_CTS); - schedule_work(&port->bh_tqueue); + tty_wakeup(tty); } } else if (!(header & ISI_CTS)) { port->tty->hw_stopped = 1; @@ -695,6 +684,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) tty_flip_buffer_push(tty); } outw(0x0000, base+0x04); /* enable interrupts */ + spin_unlock(&card->card_lock); return IRQ_HANDLED; } @@ -720,7 +710,8 @@ static void isicom_config_port(struct isi_port *port) * respectively. */ - if (baud < 1 || baud > 2) + /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ + if (baud < 1 || baud > 4) port->tty->termios->c_cflag &= ~CBAUDEX; else baud += 15; @@ -736,6 +727,10 @@ static void isicom_config_port(struct isi_port *port) baud++; /* 57.6 Kbps */ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) baud +=2; /* 115 Kbps */ + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + baud += 3; /* 230 kbps*/ + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + baud += 4; /* 460 kbps*/ } if (linuxb_to_isib[baud] == -1) { /* hang up */ @@ -1460,17 +1455,6 @@ static void isicom_start(struct tty_struct *tty) port->status |= ISI_TXOK; } -/* hangup et all */ -static void do_isicom_hangup(struct work_struct *work) -{ - struct isi_port *port = container_of(work, struct isi_port, hangup_tq); - struct tty_struct *tty; - - tty = port->tty; - if (tty) - tty_hangup(tty); -} - static void isicom_hangup(struct tty_struct *tty) { struct isi_port *port = tty->driver_data; @@ -1503,7 +1487,6 @@ static void isicom_flush_buffer(struct tty_struct *tty) port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; spin_unlock_irqrestore(&card->card_lock, flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -1536,7 +1519,7 @@ static int __devinit reset_card(struct pci_dev *pdev, { struct isi_board *board = pci_get_drvdata(pdev); unsigned long base = board->base; - unsigned int portcount = 0; + unsigned int sig, portcount = 0; int retval = 0; dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, @@ -1544,27 +1527,35 @@ static int __devinit reset_card(struct pci_dev *pdev, inw(base + 0x8); - mdelay(10); + msleep(10); outw(0, base + 0x8); /* Reset */ - msleep(3000); + msleep(1000); - *signature = inw(base + 0x4) & 0xff; + sig = inw(base + 0x4) & 0xff; + + if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd && + sig != 0xee) { + dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible " + "bad I/O Port Address 0x%lx).\n", card + 1, base); + dev_dbg(&pdev->dev, "Sig=0x%x\n", sig); + retval = -EIO; + goto end; + } + + msleep(10); portcount = inw(base + 0x2); - if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && - (portcount != 4) && (portcount != 8))) { - dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", - inw(base + 0x2), inw(base + 0xe)); - dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " - "(Possible bad I/O Port Address 0x%lx).\n", - card + 1, base); + if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 && + portcount != 8 && portcount != 16)) { + dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.", + card + 1); retval = -EIO; goto end; } - switch (*signature) { + switch (sig) { case 0xa5: case 0xbb: case 0xdd: @@ -1572,16 +1563,13 @@ static int __devinit reset_card(struct pci_dev *pdev, board->shift_count = 12; break; case 0xcc: + case 0xee: board->port_count = 16; board->shift_count = 11; break; - default: - dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible " - "bad I/O Port Address 0x%lx).\n", card + 1, base); - dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature); - retval = -EIO; } dev_info(&pdev->dev, "-Done\n"); + *signature = sig; end: return retval; @@ -1757,7 +1745,7 @@ end: /* * Insmod can set static symbols so keep these static */ -static int card; +static unsigned int card_count; static int __devinit isicom_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -1767,7 +1755,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, u8 pciirq; struct isi_board *board = NULL; - if (card >= BOARD_COUNT) + if (card_count >= BOARD_COUNT) goto err; ioaddr = pci_resource_start(pdev, 3); @@ -1785,7 +1773,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, board->index = index; board->base = ioaddr; board->irq = pciirq; - card++; + card_count++; pci_set_drvdata(pdev, board); @@ -1795,7 +1783,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, "will be disabled.\n", board->base, board->base + 15, index + 1); retval = -EBUSY; - goto err; + goto errdec; } retval = request_irq(board->irq, isicom_interrupt, @@ -1824,8 +1812,10 @@ errunri: free_irq(board->irq, board); errunrr: pci_release_region(pdev, 3); -err: +errdec: board->base = 0; + card_count--; +err: return retval; } @@ -1839,6 +1829,8 @@ static void __devexit isicom_remove(struct pci_dev *pdev) free_irq(board->irq, board); pci_release_region(pdev, 3); + board->base = 0; + card_count--; } static int __init isicom_init(void) @@ -1846,8 +1838,6 @@ static int __init isicom_init(void) int retval, idx, channel; struct isi_port *port; - card = 0; - for(idx = 0; idx < BOARD_COUNT; idx++) { port = &isi_ports[idx * 16]; isi_card[idx].ports = port; @@ -1858,8 +1848,6 @@ static int __init isicom_init(void) port->channel = channel; port->close_delay = 50 * HZ/100; port->closing_wait = 3000 * HZ/100; - INIT_WORK(&port->hangup_tq, do_isicom_hangup); - INIT_WORK(&port->bh_tqueue, isicom_bottomhalf); port->status = 0; init_waitqueue_head(&port->open_wait); init_waitqueue_head(&port->close_wait); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 68645d3..7b279d1 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -2424,7 +2424,6 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) if (tty != NULL) { tty_wakeup(tty); EBRDENABLE(brdp); - wake_up_interruptible(&tty->write_wait); } } diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7a6c1c0..cb8d691 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -595,15 +595,8 @@ static void fn_spawn_con(struct vc_data *vc) static void fn_SAK(struct vc_data *vc) { - struct tty_struct *tty = vc->vc_tty; - - /* - * SAK should also work in all raw modes and reset - * them properly. - */ - if (tty) - do_SAK(tty); - reset_vc(vc); + struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; + schedule_work(SAK_work); } static void fn_null(struct vc_data *vc) diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 0afb7ba..57f9115 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c @@ -46,7 +46,7 @@ LIST_HEAD(soft_list); /* * file operations */ -struct file_operations mbcs_ops = { +const struct file_operations mbcs_ops = { .open = mbcs_open, .llseek = mbcs_sram_llseek, .read = mbcs_sram_read, diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index f391a24..7dbaee8d 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -11,15 +11,6 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -55,36 +46,20 @@ #include <asm/io.h> #include <asm/uaccess.h> -#define MOXA_VERSION "5.1k" +#define MOXA_VERSION "5.1k" -#define MOXAMAJOR 172 -#define MOXACUMAJOR 173 +#define MOXAMAJOR 172 +#define MOXACUMAJOR 173 -#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2) -#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2) - -#define MAX_BOARDS 4 /* Don't change this value */ +#define MAX_BOARDS 4 /* Don't change this value */ #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ -#define MAX_PORTS 128 /* Don't change this value */ +#define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) /* * Define the Moxa PCI vendor and device IDs. */ -#define MOXA_BUS_TYPE_ISA 0 -#define MOXA_BUS_TYPE_PCI 1 - -#ifndef PCI_VENDOR_ID_MOXA -#define PCI_VENDOR_ID_MOXA 0x1393 -#endif -#ifndef PCI_DEVICE_ID_CP204J -#define PCI_DEVICE_ID_CP204J 0x2040 -#endif -#ifndef PCI_DEVICE_ID_C218 -#define PCI_DEVICE_ID_C218 0x2180 -#endif -#ifndef PCI_DEVICE_ID_C320 -#define PCI_DEVICE_ID_C320 0x3200 -#endif +#define MOXA_BUS_TYPE_ISA 0 +#define MOXA_BUS_TYPE_PCI 1 enum { MOXA_BOARD_C218_PCI = 1, @@ -105,47 +80,56 @@ static char *moxa_brdname[] = #ifdef CONFIG_PCI static struct pci_device_id moxa_pcibrds[] = { - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, MOXA_BOARD_C218_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, MOXA_BOARD_C320_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, MOXA_BOARD_CP204J }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218), + .driver_data = MOXA_BOARD_C218_PCI }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320), + .driver_data = MOXA_BOARD_C320_PCI }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J), + .driver_data = MOXA_BOARD_CP204J }, { 0 } }; MODULE_DEVICE_TABLE(pci, moxa_pcibrds); #endif /* CONFIG_PCI */ -typedef struct _moxa_isa_board_conf { +struct moxa_isa_board_conf { int boardType; int numPorts; unsigned long baseAddr; -} moxa_isa_board_conf; +}; -static moxa_isa_board_conf moxa_isa_boards[] = +static struct moxa_isa_board_conf moxa_isa_boards[] = { /* {MOXA_BOARD_C218_ISA,8,0xDC000}, */ }; -typedef struct _moxa_pci_devinfo { - ushort busNum; - ushort devNum; - struct pci_dev *pdev; -} moxa_pci_devinfo; - -typedef struct _moxa_board_conf { +static struct moxa_board_conf { int boardType; int numPorts; unsigned long baseAddr; int busType; - moxa_pci_devinfo pciInfo; -} moxa_board_conf; -static moxa_board_conf moxa_boards[MAX_BOARDS]; -static void __iomem *moxaBaseAddr[MAX_BOARDS]; -static int loadstat[MAX_BOARDS]; + int loadstat; + + void __iomem *basemem; + void __iomem *intNdx; + void __iomem *intPend; + void __iomem *intTable; +} moxa_boards[MAX_BOARDS]; + +struct mxser_mstatus { + tcflag_t cflag; + int cts; + int dsr; + int ri; + int dcd; +}; + +struct moxaq_str { + int inq; + int outq; +}; -struct moxa_str { +struct moxa_port { int type; int port; int close_delay; @@ -159,18 +143,18 @@ struct moxa_str { int cflag; wait_queue_head_t open_wait; wait_queue_head_t close_wait; - struct work_struct tqueue; -}; -struct mxser_mstatus { - tcflag_t cflag; - int cts; - int dsr; - int ri; - int dcd; -}; + struct timer_list emptyTimer; -static struct mxser_mstatus GMStatus[MAX_PORTS]; + char chkPort; + char lineCtrl; + void __iomem *tableAddr; + long curBaud; + char DCDState; + char lowChkFlag; + + ushort breakCnt; +}; /* statusflags */ #define TXSTOPPED 0x1 @@ -178,25 +162,17 @@ static struct mxser_mstatus GMStatus[MAX_PORTS]; #define EMPTYWAIT 0x4 #define THROTTLE 0x8 -/* event */ -#define MOXA_EVENT_HANGUP 1 - #define SERIAL_DO_RESTART - -#define SERIAL_TYPE_NORMAL 1 - #define WAKEUP_CHARS 256 -#define PORTNO(x) ((x)->index) - static int verbose = 0; static int ttymajor = MOXAMAJOR; /* Variables for insmod */ #ifdef MODULE -static int baseaddr[] = {0, 0, 0, 0}; -static int type[] = {0, 0, 0, 0}; -static int numports[] = {0, 0, 0, 0}; +static int baseaddr[4]; +static int type[4]; +static int numports[4]; #endif MODULE_AUTHOR("William Chen"); @@ -210,19 +186,9 @@ module_param_array(numports, int, NULL, 0); module_param(ttymajor, int, 0); module_param(verbose, bool, 0644); -static struct tty_driver *moxaDriver; -static struct moxa_str moxaChannels[MAX_PORTS]; -static unsigned char *moxaXmitBuff; -static int moxaTimer_on; -static struct timer_list moxaTimer; -static int moxaEmptyTimer_on[MAX_PORTS]; -static struct timer_list moxaEmptyTimer[MAX_PORTS]; -static struct semaphore moxaBuffSem; - /* * static functions: */ -static void do_moxa_softint(struct work_struct *); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); static int moxa_write(struct tty_struct *, const unsigned char *, int); @@ -244,11 +210,11 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, static void moxa_poll(unsigned long); static void set_tty_param(struct tty_struct *); static int block_till_ready(struct tty_struct *, struct file *, - struct moxa_str *); + struct moxa_port *); static void setup_empty_event(struct tty_struct *); static void check_xmit_empty(unsigned long); -static void shut_down(struct moxa_str *); -static void receive_data(struct moxa_str *); +static void shut_down(struct moxa_port *); +static void receive_data(struct moxa_port *); /* * moxa board interface functions: */ @@ -278,8 +244,8 @@ static void MoxaPortTxDisable(int); static void MoxaPortTxEnable(int); static int MoxaPortResetBrkCnt(int); static void MoxaPortSendBreak(int, int); -static int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *); -static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *); +static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *); +static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *); static void MoxaSetFifo(int port, int enable); static const struct tty_operations moxa_ops = { @@ -302,12 +268,41 @@ static const struct tty_operations moxa_ops = { .tiocmset = moxa_tiocmset, }; +static struct tty_driver *moxaDriver; +static struct moxa_port moxa_ports[MAX_PORTS]; +static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); static DEFINE_SPINLOCK(moxa_lock); #ifdef CONFIG_PCI -static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board) +static int __devinit moxa_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - board->baseAddr = pci_resource_start (p, 2); + struct moxa_board_conf *board; + unsigned int i; + int board_type = ent->driver_data; + int retval; + + retval = pci_enable_device(pdev); + if (retval) + goto err; + + for (i = 0; i < MAX_BOARDS; i++) + if (moxa_boards[i].basemem == NULL) + break; + + retval = -ENODEV; + if (i >= MAX_BOARDS) { + if (verbose) + printk("More than %d MOXA Intellio family boards " + "found. Board is ignored.\n", MAX_BOARDS); + goto err; + } + + board = &moxa_boards[i]; + board->basemem = pci_iomap(pdev, 2, 0x4000); + if (board->basemem == NULL) + goto err; + board->boardType = board_type; switch (board_type) { case MOXA_BOARD_C218_ISA: @@ -323,27 +318,40 @@ static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf break; } board->busType = MOXA_BUS_TYPE_PCI; - board->pciInfo.busNum = p->bus->number; - board->pciInfo.devNum = p->devfn >> 3; - board->pciInfo.pdev = p; - /* don't lose the reference in the next pci_get_device iteration */ - pci_dev_get(p); + + pci_set_drvdata(pdev, board); return (0); +err: + return retval; } + +static void __devexit moxa_pci_remove(struct pci_dev *pdev) +{ + struct moxa_board_conf *brd = pci_get_drvdata(pdev); + + pci_iounmap(pdev, brd->basemem); + brd->basemem = NULL; +} + +static struct pci_driver moxa_pci_driver = { + .name = "moxa", + .id_table = moxa_pcibrds, + .probe = moxa_pci_probe, + .remove = __devexit_p(moxa_pci_remove) +}; #endif /* CONFIG_PCI */ static int __init moxa_init(void) { - int i, numBoards; - struct moxa_str *ch; + int i, numBoards, retval = 0; + struct moxa_port *ch; printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); moxaDriver = alloc_tty_driver(MAX_PORTS + 1); if (!moxaDriver) return -ENOMEM; - init_MUTEX(&moxaBuffSem); moxaDriver->owner = THIS_MODULE; moxaDriver->name = "ttyMX"; moxaDriver->major = ttymajor; @@ -351,40 +359,25 @@ static int __init moxa_init(void) moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; moxaDriver->subtype = SERIAL_TYPE_NORMAL; moxaDriver->init_termios = tty_std_termios; - moxaDriver->init_termios.c_iflag = 0; - moxaDriver->init_termios.c_oflag = 0; moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; - moxaDriver->init_termios.c_lflag = 0; moxaDriver->init_termios.c_ispeed = 9600; moxaDriver->init_termios.c_ospeed = 9600; moxaDriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(moxaDriver, &moxa_ops); - moxaXmitBuff = NULL; - - for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { + for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) { ch->type = PORT_16550A; ch->port = i; - INIT_WORK(&ch->tqueue, do_moxa_softint); - ch->tty = NULL; ch->close_delay = 5 * HZ / 10; ch->closing_wait = 30 * HZ; - ch->count = 0; - ch->blocked_open = 0; ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; init_waitqueue_head(&ch->open_wait); init_waitqueue_head(&ch->close_wait); - } - for (i = 0; i < MAX_BOARDS; i++) { - moxa_boards[i].boardType = 0; - moxa_boards[i].numPorts = 0; - moxa_boards[i].baseAddr = 0; - moxa_boards[i].busType = 0; - moxa_boards[i].pciInfo.busNum = 0; - moxa_boards[i].pciInfo.devNum = 0; + setup_timer(&ch->emptyTimer, check_xmit_empty, + (unsigned long)ch); } - MoxaDriverInit(); + printk("Tty devices major number = %d\n", ttymajor); if (tty_register_driver(moxaDriver)) { @@ -392,18 +385,8 @@ static int __init moxa_init(void) put_tty_driver(moxaDriver); return -1; } - for (i = 0; i < MAX_PORTS; i++) { - init_timer(&moxaEmptyTimer[i]); - moxaEmptyTimer[i].function = check_xmit_empty; - moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i]; - moxaEmptyTimer_on[i] = 0; - } - init_timer(&moxaTimer); - moxaTimer.function = moxa_poll; - moxaTimer.expires = jiffies + (HZ / 50); - moxaTimer_on = 1; - add_timer(&moxaTimer); + mod_timer(&moxaTimer, jiffies + HZ / 50); /* Find the boards defined in source code */ numBoards = 0; @@ -451,35 +434,22 @@ static int __init moxa_init(void) } } #endif - /* Find PCI boards here */ + #ifdef CONFIG_PCI - { - struct pci_dev *p = NULL; - int n = ARRAY_SIZE(moxa_pcibrds) - 1; - i = 0; - while (i < n) { - while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL) - { - if (pci_enable_device(p)) - continue; - if (numBoards >= MAX_BOARDS) { - if (verbose) - printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS); - } else { - moxa_get_PCI_conf(p, moxa_pcibrds[i].driver_data, - &moxa_boards[numBoards]); - numBoards++; - } - } - i++; - } + retval = pci_register_driver(&moxa_pci_driver); + if (retval) { + printk(KERN_ERR "Can't register moxa pci driver!\n"); + if (numBoards) + retval = 0; } #endif + for (i = 0; i < numBoards; i++) { - moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000); + moxa_boards[i].basemem = ioremap(moxa_boards[i].baseAddr, + 0x4000); } - return (0); + return retval; } static void __exit moxa_exit(void) @@ -489,23 +459,22 @@ static void __exit moxa_exit(void) if (verbose) printk("Unloading module moxa ...\n"); - if (moxaTimer_on) - del_timer(&moxaTimer); + del_timer_sync(&moxaTimer); for (i = 0; i < MAX_PORTS; i++) - if (moxaEmptyTimer_on[i]) - del_timer(&moxaEmptyTimer[i]); + del_timer_sync(&moxa_ports[i].emptyTimer); if (tty_unregister_driver(moxaDriver)) printk("Couldn't unregister MOXA Intellio family serial driver\n"); put_tty_driver(moxaDriver); - for (i = 0; i < MAX_BOARDS; i++) { - if (moxaBaseAddr[i]) - iounmap(moxaBaseAddr[i]); - if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI) - pci_dev_put(moxa_boards[i].pciInfo.pdev); - } +#ifdef CONFIG_PCI + pci_unregister_driver(&moxa_pci_driver); +#endif + + for (i = 0; i < MAX_BOARDS; i++) + if (moxa_boards[i].basemem) + iounmap(moxa_boards[i].basemem); if (verbose) printk("Done\n"); @@ -514,28 +483,13 @@ static void __exit moxa_exit(void) module_init(moxa_init); module_exit(moxa_exit); -static void do_moxa_softint(struct work_struct *work) -{ - struct moxa_str *ch = container_of(work, struct moxa_str, tqueue); - struct tty_struct *tty; - - if (ch && (tty = ch->tty)) { - if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) { - tty_hangup(tty); /* FIXME: module removal race here - AKPM */ - wake_up_interruptible(&ch->open_wait); - ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; - } - } -} - static int moxa_open(struct tty_struct *tty, struct file *filp) { - struct moxa_str *ch; + struct moxa_port *ch; int port; int retval; - unsigned long page; - port = PORTNO(tty); + port = tty->index; if (port == MAX_PORTS) { return (0); } @@ -543,23 +497,8 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; return (-ENODEV); } - down(&moxaBuffSem); - if (!moxaXmitBuff) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - up(&moxaBuffSem); - return (-ENOMEM); - } - /* This test is guarded by the BuffSem so no longer needed - delete me in 2.5 */ - if (moxaXmitBuff) - free_page(page); - else - moxaXmitBuff = (unsigned char *) page; - } - up(&moxaBuffSem); - ch = &moxaChannels[port]; + ch = &moxa_ports[port]; ch->count++; tty->driver_data = ch; ch->tty = tty; @@ -585,10 +524,10 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) static void moxa_close(struct tty_struct *tty, struct file *filp) { - struct moxa_str *ch; + struct moxa_port *ch; int port; - port = PORTNO(tty); + port = tty->index; if (port == MAX_PORTS) { return; } @@ -605,7 +544,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) if (tty_hung_up_p(filp)) { return; } - ch = (struct moxa_str *) tty->driver_data; + ch = (struct moxa_port *) tty->driver_data; if ((tty->count == 1) && (ch->count != 1)) { printk("moxa_close: bad serial port count; tty->count is 1, " @@ -626,8 +565,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) if (ch->asyncflags & ASYNC_INITIALIZED) { setup_empty_event(tty); tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ - moxaEmptyTimer_on[ch->port] = 0; - del_timer(&moxaEmptyTimer[ch->port]); + del_timer_sync(&moxa_ports[ch->port].emptyTimer); } shut_down(ch); MoxaPortFlushData(port, 2); @@ -652,11 +590,11 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) static int moxa_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct moxa_str *ch; + struct moxa_port *ch; int len, port; unsigned long flags; - ch = (struct moxa_str *) tty->driver_data; + ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return (0); port = ch->port; @@ -675,11 +613,11 @@ static int moxa_write(struct tty_struct *tty, static int moxa_write_room(struct tty_struct *tty) { - struct moxa_str *ch; + struct moxa_port *ch; if (tty->stopped) return (0); - ch = (struct moxa_str *) tty->driver_data; + ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return (0); return (MoxaPortTxFree(ch->port)); @@ -687,7 +625,7 @@ static int moxa_write_room(struct tty_struct *tty) static void moxa_flush_buffer(struct tty_struct *tty) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return; @@ -698,7 +636,7 @@ static void moxa_flush_buffer(struct tty_struct *tty) static int moxa_chars_in_buffer(struct tty_struct *tty) { int chars; - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; /* * Sigh...I have to check if driver_data is NULL here, because @@ -730,17 +668,16 @@ static void moxa_flush_chars(struct tty_struct *tty) static void moxa_put_char(struct tty_struct *tty, unsigned char c) { - struct moxa_str *ch; + struct moxa_port *ch; int port; unsigned long flags; - ch = (struct moxa_str *) tty->driver_data; + ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return; port = ch->port; spin_lock_irqsave(&moxa_lock, flags); - moxaXmitBuff[0] = c; - MoxaPortWriteData(port, moxaXmitBuff, 1); + MoxaPortWriteData(port, &c, 1); spin_unlock_irqrestore(&moxa_lock, flags); /************************************************ if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) ) @@ -750,11 +687,11 @@ static void moxa_put_char(struct tty_struct *tty, unsigned char c) static int moxa_tiocmget(struct tty_struct *tty, struct file *file) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; int port; int flag = 0, dtr, rts; - port = PORTNO(tty); + port = tty->index; if ((port != MAX_PORTS) && (!ch)) return (-EINVAL); @@ -776,11 +713,11 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) static int moxa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; int port; int dtr, rts; - port = PORTNO(tty); + port = tty->index; if ((port != MAX_PORTS) && (!ch)) return (-EINVAL); @@ -800,12 +737,12 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, static int moxa_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; register int port; void __user *argp = (void __user *)arg; int retval; - port = PORTNO(tty); + port = tty->index; if ((port != MAX_PORTS) && (!ch)) return (-EINVAL); @@ -853,14 +790,14 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, static void moxa_throttle(struct tty_struct *tty) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; ch->statusflags |= THROTTLE; } static void moxa_unthrottle(struct tty_struct *tty) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; ch->statusflags &= ~THROTTLE; } @@ -868,7 +805,7 @@ static void moxa_unthrottle(struct tty_struct *tty) static void moxa_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return; @@ -880,7 +817,7 @@ static void moxa_set_termios(struct tty_struct *tty, static void moxa_stop(struct tty_struct *tty) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return; @@ -891,7 +828,7 @@ static void moxa_stop(struct tty_struct *tty) static void moxa_start(struct tty_struct *tty) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; if (ch == NULL) return; @@ -905,7 +842,7 @@ static void moxa_start(struct tty_struct *tty) static void moxa_hangup(struct tty_struct *tty) { - struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + struct moxa_port *ch = (struct moxa_port *) tty->driver_data; moxa_flush_buffer(tty); shut_down(ch); @@ -919,24 +856,20 @@ static void moxa_hangup(struct tty_struct *tty) static void moxa_poll(unsigned long ignored) { register int card; - struct moxa_str *ch; + struct moxa_port *ch; struct tty_struct *tp; int i, ports; - moxaTimer_on = 0; del_timer(&moxaTimer); if (MoxaDriverPoll() < 0) { - moxaTimer.function = moxa_poll; - moxaTimer.expires = jiffies + (HZ / 50); - moxaTimer_on = 1; - add_timer(&moxaTimer); + mod_timer(&moxaTimer, jiffies + HZ / 50); return; } for (card = 0; card < MAX_BOARDS; card++) { if ((ports = MoxaPortsOfCard(card)) <= 0) continue; - ch = &moxaChannels[card * MAX_PORTS_PER_BOARD]; + ch = &moxa_ports[card * MAX_PORTS_PER_BOARD]; for (i = 0; i < ports; i++, ch++) { if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) continue; @@ -962,18 +895,16 @@ static void moxa_poll(unsigned long ignored) if (MoxaPortDCDON(ch->port)) wake_up_interruptible(&ch->open_wait); else { - set_bit(MOXA_EVENT_HANGUP, &ch->event); - schedule_work(&ch->tqueue); + tty_hangup(tp); + wake_up_interruptible(&ch->open_wait); + ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; } } } } } - moxaTimer.function = moxa_poll; - moxaTimer.expires = jiffies + (HZ / 50); - moxaTimer_on = 1; - add_timer(&moxaTimer); + mod_timer(&moxaTimer, jiffies + HZ / 50); } /******************************************************************************/ @@ -981,10 +912,10 @@ static void moxa_poll(unsigned long ignored) static void set_tty_param(struct tty_struct *tty) { register struct ktermios *ts; - struct moxa_str *ch; + struct moxa_port *ch; int rts, cts, txflow, rxflow, xany; - ch = (struct moxa_str *) tty->driver_data; + ch = (struct moxa_port *) tty->driver_data; ts = tty->termios; if (ts->c_cflag & CLOCAL) ch->asyncflags &= ~ASYNC_CHECK_CD; @@ -1004,7 +935,7 @@ static void set_tty_param(struct tty_struct *tty) } static int block_till_ready(struct tty_struct *tty, struct file *filp, - struct moxa_str *ch) + struct moxa_port *ch) { DECLARE_WAITQUEUE(wait,current); unsigned long flags; @@ -1095,40 +1026,33 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp, static void setup_empty_event(struct tty_struct *tty) { - struct moxa_str *ch = tty->driver_data; + struct moxa_port *ch = tty->driver_data; unsigned long flags; spin_lock_irqsave(&moxa_lock, flags); ch->statusflags |= EMPTYWAIT; - moxaEmptyTimer_on[ch->port] = 0; - del_timer(&moxaEmptyTimer[ch->port]); - moxaEmptyTimer[ch->port].expires = jiffies + HZ; - moxaEmptyTimer_on[ch->port] = 1; - add_timer(&moxaEmptyTimer[ch->port]); + mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ); spin_unlock_irqrestore(&moxa_lock, flags); } static void check_xmit_empty(unsigned long data) { - struct moxa_str *ch; + struct moxa_port *ch; - ch = (struct moxa_str *) data; - moxaEmptyTimer_on[ch->port] = 0; - del_timer(&moxaEmptyTimer[ch->port]); + ch = (struct moxa_port *) data; + del_timer_sync(&moxa_ports[ch->port].emptyTimer); if (ch->tty && (ch->statusflags & EMPTYWAIT)) { if (MoxaPortTxQueue(ch->port) == 0) { ch->statusflags &= ~EMPTYWAIT; tty_wakeup(ch->tty); return; } - moxaEmptyTimer[ch->port].expires = jiffies + HZ; - moxaEmptyTimer_on[ch->port] = 1; - add_timer(&moxaEmptyTimer[ch->port]); + mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ); } else ch->statusflags &= ~EMPTYWAIT; } -static void shut_down(struct moxa_str *ch) +static void shut_down(struct moxa_port *ch) { struct tty_struct *tp; @@ -1148,7 +1072,7 @@ static void shut_down(struct moxa_str *ch) ch->asyncflags &= ~ASYNC_INITIALIZED; } -static void receive_data(struct moxa_str *ch) +static void receive_data(struct moxa_port *ch) { struct tty_struct *tp; struct ktermios *ts; @@ -1465,35 +1389,21 @@ static void receive_data(struct moxa_str *ch) /* * Query */ -#define QueryPort MAX_PORTS - - struct mon_str { int tick; int rxcnt[MAX_PORTS]; int txcnt[MAX_PORTS]; }; -typedef struct mon_str mon_st; #define DCD_changed 0x01 #define DCD_oldstate 0x80 static unsigned char moxaBuff[10240]; -static void __iomem *moxaIntNdx[MAX_BOARDS]; -static void __iomem *moxaIntPend[MAX_BOARDS]; -static void __iomem *moxaIntTable[MAX_BOARDS]; -static char moxaChkPort[MAX_PORTS]; -static char moxaLineCtrl[MAX_PORTS]; -static void __iomem *moxaTableAddr[MAX_PORTS]; -static long moxaCurBaud[MAX_PORTS]; -static char moxaDCDState[MAX_PORTS]; -static char moxaLowChkFlag[MAX_PORTS]; static int moxaLowWaterChk; static int moxaCard; -static mon_st moxaLog; -static int moxaFuncTout; -static ushort moxaBreakCnt[MAX_PORTS]; +static struct mon_str moxaLog; +static int moxaFuncTout = HZ / 2; static void moxadelay(int); static void moxafunc(void __iomem *, int, ushort); @@ -1514,16 +1424,18 @@ static int moxaloadc320(int, void __iomem *, int, int *); *****************************************************************************/ void MoxaDriverInit(void) { - int i; + struct moxa_port *p; + unsigned int i; moxaFuncTout = HZ / 2; /* 500 mini-seconds */ moxaCard = 0; moxaLog.tick = 0; moxaLowWaterChk = 0; for (i = 0; i < MAX_PORTS; i++) { - moxaChkPort[i] = 0; - moxaLowChkFlag[i] = 0; - moxaLineCtrl[i] = 0; + p = &moxa_ports[i]; + p->chkPort = 0; + p->lowChkFlag = 0; + p->lineCtrl = 0; moxaLog.rxcnt[i] = 0; moxaLog.txcnt[i] = 0; } @@ -1545,19 +1457,12 @@ void MoxaDriverInit(void) #define MOXA_GET_CUMAJOR (MOXA + 64) #define MOXA_GETMSTATUS (MOXA + 65) - -struct moxaq_str { - int inq; - int outq; -}; - struct dl_str { char __user *buf; int len; int cardno; }; -static struct moxaq_str temp_queue[MAX_PORTS]; static struct dl_str dltmp; void MoxaPortFlushData(int port, int mode) @@ -1565,10 +1470,10 @@ void MoxaPortFlushData(int port, int mode) void __iomem *ofsAddr; if ((mode < 0) || (mode > 2)) return; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_FlushQueue, mode); if (mode != 1) { - moxaLowChkFlag[port] = 0; + moxa_ports[port].lowChkFlag = 0; low_water_check(ofsAddr); } } @@ -1580,7 +1485,7 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) int MoxaPortTxQueue(int), MoxaPortRxQueue(int); void __user *argp = (void __user *)arg; - if (port == QueryPort) { + if (port == MAX_PORTS) { if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) && (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) && (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) && @@ -1590,7 +1495,8 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) } switch (cmd) { case MOXA_GET_CONF: - if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf))) + if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * + sizeof(struct moxa_board_conf))) return -EFAULT; return (0); case MOXA_INIT_DRIVER: @@ -1599,23 +1505,27 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) return (0); case MOXA_GETDATACOUNT: moxaLog.tick = jiffies; - if(copy_to_user(argp, &moxaLog, sizeof(mon_st))) + if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str))) return -EFAULT; return (0); case MOXA_FLUSH_QUEUE: MoxaPortFlushData(port, arg); return (0); - case MOXA_GET_IOQUEUE: - for (i = 0; i < MAX_PORTS; i++) { - if (moxaChkPort[i]) { - temp_queue[i].inq = MoxaPortRxQueue(i); - temp_queue[i].outq = MoxaPortTxQueue(i); + case MOXA_GET_IOQUEUE: { + struct moxaq_str __user *argm = argp; + struct moxaq_str tmp; + + for (i = 0; i < MAX_PORTS; i++, argm++) { + memset(&tmp, 0, sizeof(tmp)); + if (moxa_ports[i].chkPort) { + tmp.inq = MoxaPortRxQueue(i); + tmp.outq = MoxaPortTxQueue(i); } + if (copy_to_user(argm, &tmp, sizeof(tmp))) + return -EFAULT; } - if(copy_to_user(argp, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS)) - return -EFAULT; return (0); - case MOXA_GET_OQUEUE: + } case MOXA_GET_OQUEUE: i = MoxaPortTxQueue(port); return put_user(i, (unsigned long __user *)argp); case MOXA_GET_IQUEUE: @@ -1630,33 +1540,36 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) if(copy_to_user(argp, &i, sizeof(int))) return -EFAULT; return 0; - case MOXA_GETMSTATUS: - for (i = 0; i < MAX_PORTS; i++) { - GMStatus[i].ri = 0; - GMStatus[i].dcd = 0; - GMStatus[i].dsr = 0; - GMStatus[i].cts = 0; - if (!moxaChkPort[i]) { - continue; + case MOXA_GETMSTATUS: { + struct mxser_mstatus __user *argm = argp; + struct mxser_mstatus tmp; + struct moxa_port *p; + + for (i = 0; i < MAX_PORTS; i++, argm++) { + p = &moxa_ports[i]; + memset(&tmp, 0, sizeof(tmp)); + if (!p->chkPort) { + goto copy; } else { - status = MoxaPortLineStatus(moxaChannels[i].port); + status = MoxaPortLineStatus(p->port); if (status & 1) - GMStatus[i].cts = 1; + tmp.cts = 1; if (status & 2) - GMStatus[i].dsr = 1; + tmp.dsr = 1; if (status & 4) - GMStatus[i].dcd = 1; + tmp.dcd = 1; } - if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios) - GMStatus[i].cflag = moxaChannels[i].cflag; + if (!p->tty || !p->tty->termios) + tmp.cflag = p->cflag; else - GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag; + tmp.cflag = p->tty->termios->c_cflag; +copy: + if (copy_to_user(argm, &tmp, sizeof(tmp))) + return -EFAULT; } - if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS)) - return -EFAULT; return 0; - default: + } default: return (-ENOIOCTLCMD); case MOXA_LOAD_BIOS: case MOXA_FIND_BOARD: @@ -1694,6 +1607,7 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) int MoxaDriverPoll(void) { + struct moxa_board_conf *brd; register ushort temp; register int card; void __iomem *ofsAddr; @@ -1703,43 +1617,44 @@ int MoxaDriverPoll(void) if (moxaCard == 0) return (-1); for (card = 0; card < MAX_BOARDS; card++) { - if (loadstat[card] == 0) + brd = &moxa_boards[card]; + if (brd->loadstat == 0) continue; - if ((ports = moxa_boards[card].numPorts) == 0) + if ((ports = brd->numPorts) == 0) continue; - if (readb(moxaIntPend[card]) == 0xff) { - ip = moxaIntTable[card] + readb(moxaIntNdx[card]); + if (readb(brd->intPend) == 0xff) { + ip = brd->intTable + readb(brd->intNdx); p = card * MAX_PORTS_PER_BOARD; ports <<= 1; for (port = 0; port < ports; port += 2, p++) { if ((temp = readw(ip + port)) != 0) { writew(0, ip + port); - ofsAddr = moxaTableAddr[p]; + ofsAddr = moxa_ports[p].tableAddr; if (temp & IntrTx) writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat); if (temp & IntrBreak) { - moxaBreakCnt[p]++; + moxa_ports[p].breakCnt++; } if (temp & IntrLine) { if (readb(ofsAddr + FlagStat) & DCD_state) { - if ((moxaDCDState[p] & DCD_oldstate) == 0) - moxaDCDState[p] = (DCD_oldstate | + if ((moxa_ports[p].DCDState & DCD_oldstate) == 0) + moxa_ports[p].DCDState = (DCD_oldstate | DCD_changed); } else { - if (moxaDCDState[p] & DCD_oldstate) - moxaDCDState[p] = DCD_changed; + if (moxa_ports[p].DCDState & DCD_oldstate) + moxa_ports[p].DCDState = DCD_changed; } } } } - writeb(0, moxaIntPend[card]); + writeb(0, brd->intPend); } if (moxaLowWaterChk) { p = card * MAX_PORTS_PER_BOARD; for (port = 0; port < ports; port++, p++) { - if (moxaLowChkFlag[p]) { - moxaLowChkFlag[p] = 0; - ofsAddr = moxaTableAddr[p]; + if (moxa_ports[p].lowChkFlag) { + moxa_ports[p].lowChkFlag = 0; + ofsAddr = moxa_ports[p].tableAddr; low_water_check(ofsAddr); } } @@ -1767,9 +1682,7 @@ int MoxaPortsOfCard(int cardno) * 2. MoxaPortEnable(int port); * * 3. MoxaPortDisable(int port); * * 4. MoxaPortGetMaxBaud(int port); * - * 5. MoxaPortGetCurBaud(int port); * * 6. MoxaPortSetBaud(int port, long baud); * - * 7. MoxaPortSetMode(int port, int databit, int stopbit, int parity); * * 8. MoxaPortSetTermio(int port, unsigned char *termio); * * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); * * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); * @@ -1780,18 +1693,12 @@ int MoxaPortsOfCard(int cardno) * 15. MoxaPortFlushData(int port, int mode); * * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); * * 17. MoxaPortReadData(int port, struct tty_struct *tty); * - * 18. MoxaPortTxBufSize(int port); * - * 19. MoxaPortRxBufSize(int port); * * 20. MoxaPortTxQueue(int port); * * 21. MoxaPortTxFree(int port); * * 22. MoxaPortRxQueue(int port); * - * 23. MoxaPortRxFree(int port); * * 24. MoxaPortTxDisable(int port); * * 25. MoxaPortTxEnable(int port); * - * 26. MoxaPortGetBrkCnt(int port); * * 27. MoxaPortResetBrkCnt(int port); * - * 28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue); * - * 29. MoxaPortIsTxHold(int port); * * 30. MoxaPortSendBreak(int port, int ticks); * *****************************************************************************/ /* @@ -1878,15 +1785,6 @@ int MoxaPortsOfCard(int cardno) * 38400/57600/115200 bps * * - * Function 9: Get the current baud rate of this port. - * Syntax: - * long MoxaPortGetCurBaud(int port); - * int port : port number (0 - 127) - * - * return: 0 : this port is invalid - * 50 - 115200 bps - * - * * Function 10: Setting baud rate of this port. * Syntax: * long MoxaPortSetBaud(int port, long baud); @@ -1900,18 +1798,6 @@ int MoxaPortsOfCard(int cardno) * baud rate will be the maximun baud rate. * * - * Function 11: Setting the data-bits/stop-bits/parity of this port - * Syntax: - * int MoxaPortSetMode(int port, int databits, int stopbits, int parity); - * int port : port number (0 - 127) - * int databits : data bits (8/7/6/5) - * int stopbits : stop bits (2/1/0, 0 show 1.5 stop bits) - int parity : parity (0:None,1:Odd,2:Even,3:Mark,4:Space) - * - * return: -1 : invalid parameter - * 0 : setting O.K. - * - * * Function 12: Configure the port. * Syntax: * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); @@ -2016,22 +1902,6 @@ int MoxaPortsOfCard(int cardno) * return: 0 - length : real read data length * * - * Function 22: Get the Tx buffer size of this port - * Syntax: - * int MoxaPortTxBufSize(int port); - * int port : port number (0 - 127) - * - * return: .. : Tx buffer size - * - * - * Function 23: Get the Rx buffer size of this port - * Syntax: - * int MoxaPortRxBufSize(int port); - * int port : port number (0 - 127) - * - * return: .. : Rx buffer size - * - * * Function 24: Get the Tx buffer current queued data bytes * Syntax: * int MoxaPortTxQueue(int port); @@ -2056,14 +1926,6 @@ int MoxaPortsOfCard(int cardno) * return: .. : Rx buffer current queued data bytes * * - * Function 27: Get the Rx buffer current free space - * Syntax: - * int MoxaPortRxFree(int port); - * int port : port number (0 - 127) - * - * return: .. : Rx buffer current free space - * - * * Function 28: Disable port data transmission. * Syntax: * void MoxaPortTxDisable(int port); @@ -2076,14 +1938,6 @@ int MoxaPortsOfCard(int cardno) * int port : port number (0 - 127) * * - * Function 30: Get the received BREAK signal count. - * Syntax: - * int MoxaPortGetBrkCnt(int port); - * int port : port number (0 - 127) - * - * return: 0 - .. : BREAK signal count - * - * * Function 31: Get the received BREAK signal count and reset it. * Syntax: * int MoxaPortResetBrkCnt(int port); @@ -2092,25 +1946,6 @@ int MoxaPortsOfCard(int cardno) * return: 0 - .. : BREAK signal count * * - * Function 32: Set the S/W flow control new XON/XOFF value, default - * XON is 0x11 & XOFF is 0x13. - * Syntax: - * void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue); - * int port : port number (0 - 127) - * int xonValue : new XON value (0 - 255) - * int xoffValue : new XOFF value (0 - 255) - * - * - * Function 33: Check this port's transmission is hold by remote site - * because the flow control. - * Syntax: - * int MoxaPortIsTxHold(int port); - * int port : port number (0 - 127) - * - * return: 0 : normal - * 1 : hold by remote site - * - * * Function 34: Send out a BREAK signal. * Syntax: * void MoxaPortSendBreak(int port, int ms100); @@ -2125,7 +1960,7 @@ int MoxaPortIsValid(int port) if (moxaCard == 0) return (0); - if (moxaChkPort[port] == 0) + if (moxa_ports[port].chkPort == 0) return (0); return (1); } @@ -2136,9 +1971,9 @@ void MoxaPortEnable(int port) int MoxaPortLineStatus(int); short lowwater = 512; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; writew(lowwater, ofsAddr + Low_water); - moxaBreakCnt[port] = 0; + moxa_ports[port].breakCnt = 0; if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { moxafunc(ofsAddr, FC_SetBreakIrq, 0); @@ -2155,7 +1990,7 @@ void MoxaPortEnable(int port) void MoxaPortDisable(int port) { - void __iomem *ofsAddr = moxaTableAddr[port]; + void __iomem *ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); @@ -2181,7 +2016,7 @@ long MoxaPortSetBaud(int port, long baud) if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0)) return (0); - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; if (baud > max) baud = max; if (max == 38400L) @@ -2193,7 +2028,7 @@ long MoxaPortSetBaud(int port, long baud) val = clock / baud; moxafunc(ofsAddr, FC_SetBaud, val); baud = clock / val; - moxaCurBaud[port] = baud; + moxa_ports[port].curBaud = baud; return (baud); } @@ -2203,9 +2038,9 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud) tcflag_t cflag; tcflag_t mode = 0; - if (moxaChkPort[port] == 0 || termio == 0) + if (moxa_ports[port].chkPort == 0 || termio == 0) return (-1); - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; cflag = termio->c_cflag; /* termio->c_cflag */ mode = termio->c_cflag & CSIZE; @@ -2259,13 +2094,13 @@ int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState) if (!MoxaPortIsValid(port)) return (-1); if (dtrState) { - if (moxaLineCtrl[port] & DTR_ON) + if (moxa_ports[port].lineCtrl & DTR_ON) *dtrState = 1; else *dtrState = 0; } if (rtsState) { - if (moxaLineCtrl[port] & RTS_ON) + if (moxa_ports[port].lineCtrl & RTS_ON) *rtsState = 1; else *rtsState = 0; @@ -2278,13 +2113,13 @@ void MoxaPortLineCtrl(int port, int dtr, int rts) void __iomem *ofsAddr; int mode; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; mode = 0; if (dtr) mode |= DTR_ON; if (rts) mode |= RTS_ON; - moxaLineCtrl[port] = mode; + moxa_ports[port].lineCtrl = mode; moxafunc(ofsAddr, FC_LineControl, mode); } @@ -2293,7 +2128,7 @@ void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int tx void __iomem *ofsAddr; int mode; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; mode = 0; if (rts) mode |= RTS_FlowCtl; @@ -2313,7 +2148,7 @@ int MoxaPortLineStatus(int port) void __iomem *ofsAddr; int val; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { moxafunc(ofsAddr, FC_LineStatus, 0); @@ -2324,11 +2159,11 @@ int MoxaPortLineStatus(int port) val &= 0x0B; if (val & 8) { val |= 4; - if ((moxaDCDState[port] & DCD_oldstate) == 0) - moxaDCDState[port] = (DCD_oldstate | DCD_changed); + if ((moxa_ports[port].DCDState & DCD_oldstate) == 0) + moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed); } else { - if (moxaDCDState[port] & DCD_oldstate) - moxaDCDState[port] = DCD_changed; + if (moxa_ports[port].DCDState & DCD_oldstate) + moxa_ports[port].DCDState = DCD_changed; } val &= 7; return (val); @@ -2338,10 +2173,10 @@ int MoxaPortDCDChange(int port) { int n; - if (moxaChkPort[port] == 0) + if (moxa_ports[port].chkPort == 0) return (0); - n = moxaDCDState[port]; - moxaDCDState[port] &= ~DCD_changed; + n = moxa_ports[port].DCDState; + moxa_ports[port].DCDState &= ~DCD_changed; n &= DCD_changed; return (n); } @@ -2350,32 +2185,15 @@ int MoxaPortDCDON(int port) { int n; - if (moxaChkPort[port] == 0) + if (moxa_ports[port].chkPort == 0) return (0); - if (moxaDCDState[port] & DCD_oldstate) + if (moxa_ports[port].DCDState & DCD_oldstate) n = 1; else n = 0; return (n); } - -/* - int MoxaDumpMem(int port, unsigned char * buffer, int len) - { - int i; - unsigned long baseAddr,ofsAddr,ofs; - - baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; - ofs = baseAddr + DynPage_addr + pageofs; - if (len > 0x2000L) - len = 0x2000L; - for (i = 0; i < len; i++) - buffer[i] = readb(ofs+i); - } - */ - - int MoxaPortWriteData(int port, unsigned char * buffer, int len) { int c, total, i; @@ -2385,8 +2203,8 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len) ushort pageno, pageofs, bufhead; void __iomem *baseAddr, *ofsAddr, *ofs; - ofsAddr = moxaTableAddr[port]; - baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; + ofsAddr = moxa_ports[port].tableAddr; + baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; tx_mask = readw(ofsAddr + TX_mask); spage = readw(ofsAddr + Page_txb); epage = readw(ofsAddr + EndPage_txb); @@ -2448,8 +2266,8 @@ int MoxaPortReadData(int port, struct tty_struct *tty) ushort pageno, bufhead; void __iomem *baseAddr, *ofsAddr, *ofs; - ofsAddr = moxaTableAddr[port]; - baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; + ofsAddr = moxa_ports[port].tableAddr; + baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; head = readw(ofsAddr + RXrptr); tail = readw(ofsAddr + RXwptr); rx_mask = readw(ofsAddr + RX_mask); @@ -2504,7 +2322,7 @@ int MoxaPortReadData(int port, struct tty_struct *tty) } if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) { moxaLowWaterChk = 1; - moxaLowChkFlag[port] = 1; + moxa_ports[port].lowChkFlag = 1; } return (total); } @@ -2516,7 +2334,7 @@ int MoxaPortTxQueue(int port) ushort rptr, wptr, mask; int len; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; rptr = readw(ofsAddr + TXrptr); wptr = readw(ofsAddr + TXwptr); mask = readw(ofsAddr + TX_mask); @@ -2530,7 +2348,7 @@ int MoxaPortTxFree(int port) ushort rptr, wptr, mask; int len; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; rptr = readw(ofsAddr + TXrptr); wptr = readw(ofsAddr + TXwptr); mask = readw(ofsAddr + TX_mask); @@ -2544,7 +2362,7 @@ int MoxaPortRxQueue(int port) ushort rptr, wptr, mask; int len; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; rptr = readw(ofsAddr + RXrptr); wptr = readw(ofsAddr + RXwptr); mask = readw(ofsAddr + RX_mask); @@ -2557,7 +2375,7 @@ void MoxaPortTxDisable(int port) { void __iomem *ofsAddr; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_SetXoffState, Magic_code); } @@ -2565,7 +2383,7 @@ void MoxaPortTxEnable(int port) { void __iomem *ofsAddr; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_SetXonState, Magic_code); } @@ -2573,8 +2391,8 @@ void MoxaPortTxEnable(int port) int MoxaPortResetBrkCnt(int port) { ushort cnt; - cnt = moxaBreakCnt[port]; - moxaBreakCnt[port] = 0; + cnt = moxa_ports[port].breakCnt; + moxa_ports[port].breakCnt = 0; return (cnt); } @@ -2583,7 +2401,7 @@ void MoxaPortSendBreak(int port, int ms100) { void __iomem *ofsAddr; - ofsAddr = moxaTableAddr[port]; + ofsAddr = moxa_ports[port].tableAddr; if (ms100) { moxafunc(ofsAddr, FC_SendBreak, Magic_code); moxadelay(ms100 * (HZ / 10)); @@ -2594,7 +2412,7 @@ void MoxaPortSendBreak(int port, int ms100) moxafunc(ofsAddr, FC_StopBreak, Magic_code); } -static int moxa_get_serial_info(struct moxa_str *info, +static int moxa_get_serial_info(struct moxa_port *info, struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -2616,7 +2434,7 @@ static int moxa_get_serial_info(struct moxa_str *info, } -static int moxa_set_serial_info(struct moxa_str *info, +static int moxa_set_serial_info(struct moxa_port *info, struct serial_struct __user *new_info) { struct serial_struct new_serial; @@ -2713,7 +2531,7 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; - baseAddr = moxaBaseAddr[cardno]; + baseAddr = moxa_boards[cardno].basemem; writeb(HW_reset, baseAddr + Control_reg); /* reset */ moxadelay(1); /* delay 10 ms */ for (i = 0; i < 4096; i++) @@ -2729,7 +2547,7 @@ static int moxafindcard(int cardno) void __iomem *baseAddr; ushort tmp; - baseAddr = moxaBaseAddr[cardno]; + baseAddr = moxa_boards[cardno].basemem; switch (moxa_boards[cardno].boardType) { case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: @@ -2762,7 +2580,7 @@ static int moxaload320b(int cardno, unsigned char __user *tmp, int len) return -EINVAL; if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; - baseAddr = moxaBaseAddr[cardno]; + baseAddr = moxa_boards[cardno].basemem; writew(len - 7168 - 2, baseAddr + C320bapi_len); writeb(1, baseAddr + Control_reg); /* Select Page 1 */ for (i = 0; i < 7168; i++) @@ -2780,7 +2598,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; - baseAddr = moxaBaseAddr[cardno]; + baseAddr = moxa_boards[cardno].basemem; switch (moxa_boards[cardno].boardType) { case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: @@ -2790,11 +2608,13 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) return (retval); port = cardno * MAX_PORTS_PER_BOARD; for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { - moxaChkPort[port] = 1; - moxaCurBaud[port] = 9600L; - moxaDCDState[port] = 0; - moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i; - ofsAddr = moxaTableAddr[port]; + struct moxa_port *p = &moxa_ports[port]; + + p->chkPort = 1; + p->curBaud = 9600L; + p->DCDState = 0; + p->tableAddr = baseAddr + Extern_table + Extern_size * i; + ofsAddr = p->tableAddr; writew(C218rx_mask, ofsAddr + RX_mask); writew(C218tx_mask, ofsAddr + TX_mask); writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); @@ -2812,11 +2632,13 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) return (retval); port = cardno * MAX_PORTS_PER_BOARD; for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { - moxaChkPort[port] = 1; - moxaCurBaud[port] = 9600L; - moxaDCDState[port] = 0; - moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i; - ofsAddr = moxaTableAddr[port]; + struct moxa_port *p = &moxa_ports[port]; + + p->chkPort = 1; + p->curBaud = 9600L; + p->DCDState = 0; + p->tableAddr = baseAddr + Extern_table + Extern_size * i; + ofsAddr = p->tableAddr; if (moxa_boards[cardno].numPorts == 8) { writew(C320p8rx_mask, ofsAddr + RX_mask); writew(C320p8tx_mask, ofsAddr + TX_mask); @@ -2852,7 +2674,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) } break; } - loadstat[cardno] = 1; + moxa_boards[cardno].loadstat = 1; return (0); } @@ -2926,9 +2748,9 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len) return (-1); } moxaCard = 1; - moxaIntNdx[cardno] = baseAddr + IRQindex; - moxaIntPend[cardno] = baseAddr + IRQpending; - moxaIntTable[cardno] = baseAddr + IRQtable; + moxa_boards[cardno].intNdx = baseAddr + IRQindex; + moxa_boards[cardno].intPend = baseAddr + IRQpending; + moxa_boards[cardno].intTable = baseAddr + IRQtable; return (0); } @@ -3021,25 +2843,15 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor if (readw(baseAddr + Magic_no) != Magic_code) return (-102); moxaCard = 1; - moxaIntNdx[cardno] = baseAddr + IRQindex; - moxaIntPend[cardno] = baseAddr + IRQpending; - moxaIntTable[cardno] = baseAddr + IRQtable; + moxa_boards[cardno].intNdx = baseAddr + IRQindex; + moxa_boards[cardno].intPend = baseAddr + IRQpending; + moxa_boards[cardno].intTable = baseAddr + IRQtable; return (0); } -#if 0 -long MoxaPortGetCurBaud(int port) -{ - - if (moxaChkPort[port] == 0) - return (0); - return (moxaCurBaud[port]); -} -#endif /* 0 */ - static void MoxaSetFifo(int port, int enable) { - void __iomem *ofsAddr = moxaTableAddr[port]; + void __iomem *ofsAddr = moxa_ports[port].tableAddr; if (!enable) { moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); @@ -3049,132 +2861,3 @@ static void MoxaSetFifo(int port, int enable) moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); } } - -#if 0 -int MoxaPortSetMode(int port, int databits, int stopbits, int parity) -{ - void __iomem *ofsAddr; - int val; - - val = 0; - switch (databits) { - case 5: - val |= 0; - break; - case 6: - val |= 1; - break; - case 7: - val |= 2; - break; - case 8: - val |= 3; - break; - default: - return (-1); - } - switch (stopbits) { - case 0: - val |= 0; - break; /* stop bits 1.5 */ - case 1: - val |= 0; - break; - case 2: - val |= 4; - break; - default: - return (-1); - } - switch (parity) { - case 0: - val |= 0x00; - break; /* None */ - case 1: - val |= 0x08; - break; /* Odd */ - case 2: - val |= 0x18; - break; /* Even */ - case 3: - val |= 0x28; - break; /* Mark */ - case 4: - val |= 0x38; - break; /* Space */ - default: - return (-1); - } - ofsAddr = moxaTableAddr[port]; - moxafunc(ofsAddr, FC_SetMode, val); - return (0); -} - -int MoxaPortTxBufSize(int port) -{ - void __iomem *ofsAddr; - int size; - - ofsAddr = moxaTableAddr[port]; - size = readw(ofsAddr + TX_mask); - return (size); -} - -int MoxaPortRxBufSize(int port) -{ - void __iomem *ofsAddr; - int size; - - ofsAddr = moxaTableAddr[port]; - size = readw(ofsAddr + RX_mask); - return (size); -} - -int MoxaPortRxFree(int port) -{ - void __iomem *ofsAddr; - ushort rptr, wptr, mask; - int len; - - ofsAddr = moxaTableAddr[port]; - rptr = readw(ofsAddr + RXrptr); - wptr = readw(ofsAddr + RXwptr); - mask = readw(ofsAddr + RX_mask); - len = mask - ((wptr - rptr) & mask); - return (len); -} -int MoxaPortGetBrkCnt(int port) -{ - return (moxaBreakCnt[port]); -} - -void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue) -{ - void __iomem *ofsAddr; - - ofsAddr = moxaTableAddr[port]; - writew(xonValue, ofsAddr + FuncArg); - writew(xoffValue, ofsAddr + FuncArg1); - writew(FC_SetXonXoff, ofsAddr + FuncCode); - wait_finish(ofsAddr); -} - -int MoxaPortIsTxHold(int port) -{ - void __iomem *ofsAddr; - int val; - - ofsAddr = moxaTableAddr[port]; - if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || - (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { - moxafunc(ofsAddr, FC_GetCCSR, 0); - val = readw(ofsAddr + FuncArg); - if (val & 0x04) - return (1); - } else { - if (readw(ofsAddr + FlagStat) & Tx_flowOff) - return (1); - } - return (0); -} -#endif diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 235e892..7ac3061 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -291,7 +291,7 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma) return mspec_mmap(file, vma, MSPEC_UNCACHED); } -static struct file_operations fetchop_fops = { +static const struct file_operations fetchop_fops = { .owner = THIS_MODULE, .mmap = fetchop_mmap }; @@ -302,7 +302,7 @@ static struct miscdevice fetchop_miscdev = { .fops = &fetchop_fops }; -static struct file_operations cached_fops = { +static const struct file_operations cached_fops = { .owner = THIS_MODULE, .mmap = cached_mmap }; @@ -313,7 +313,7 @@ static struct miscdevice cached_miscdev = { .fops = &cached_fops }; -static struct file_operations uncached_fops = { +static const struct file_operations uncached_fops = { .owner = THIS_MODULE, .mmap = uncached_mmap }; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 83f604b..a61fb6d 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -321,8 +321,6 @@ struct mxser_struct { unsigned long event; int count; /* # of fd on device */ int blocked_open; /* # of blocked opens */ - long session; /* Session of opening process */ - long pgrp; /* pgrp of opening process */ unsigned char *xmit_buf; int xmit_head; int xmit_tail; @@ -1001,15 +999,12 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) mxser_change_speed(info, NULL); } - info->session = process_session(current); - info->pgrp = process_group(current); - /* status = mxser_get_msr(info->base, 0, info->port); mxser_check_modem_status(info, status); */ -/* unmark here for very high baud rate (ex. 921600 bps) used */ + /* unmark here for very high baud rate (ex. 921600 bps) used */ tty->low_latency = 1; return 0; } @@ -1254,9 +1249,7 @@ static void mxser_flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&info->slock, flags); /* above added by shinhay */ - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); } static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h index 7e188a4..9fe2849 100644 --- a/drivers/char/mxser.h +++ b/drivers/char/mxser.h @@ -439,12 +439,4 @@ #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) - -#ifndef INIT_WORK -#define INIT_WORK(_work, _func, _data){ \ - _data->tqueue.routine = _func;\ - _data->tqueue.data = _data;\ - } -#endif - #endif diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index 1bb030b..9af07e4 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c @@ -49,22 +49,25 @@ #include "mxser_new.h" -#define MXSER_VERSION "2.0" +#define MXSER_VERSION "2.0.1" /* 1.9.15 */ #define MXSERMAJOR 174 #define MXSERCUMAJOR 175 -#define MXSER_EVENT_TXLOW 1 - #define MXSER_BOARDS 4 /* Max. boards */ #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) -#define MXSER_ISR_PASS_LIMIT 99999L +#define MXSER_ISR_PASS_LIMIT 100 #define MXSER_ERR_IOADDR -1 #define MXSER_ERR_IRQ -2 #define MXSER_ERR_IRQ_CONFLIT -3 #define MXSER_ERR_VECTOR -4 +/*CheckIsMoxaMust return value*/ +#define MOXA_OTHER_UART 0x00 +#define MOXA_MUST_MU150_HWID 0x01 +#define MOXA_MUST_MU860_HWID 0x02 + #define WAKEUP_CHARS 256 #define UART_MCR_AFE 0x20 @@ -176,6 +179,18 @@ static struct pci_device_id mxser_pcibrds[] = { }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); +static int mxvar_baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 +}; +static unsigned int mxvar_baud_table1[] = { + 0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, + B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600 +}; +#define BAUD_TABLE_NO ARRAY_SIZE(mxvar_baud_table) + +#define B_SPEC B2000000 + static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; static int ttymajor = MXSERMAJOR; static int calloutmajor = MXSERCUMAJOR; @@ -237,8 +252,7 @@ struct mxser_port { long realbaud; int type; /* UART type */ int flags; /* defined in tty.h */ - long session; /* Session of opening process */ - long pgrp; /* pgrp of opening process */ + int speed; int x_char; /* xon/xoff character */ int IER; /* Interrupt Enable Register */ @@ -267,14 +281,11 @@ struct mxser_port { int xmit_cnt; struct ktermios normal_termios; - struct ktermios callout_termios; struct mxser_mon mon_data; spinlock_t slock; - struct work_struct tqueue; wait_queue_head_t open_wait; - wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; }; @@ -313,10 +324,9 @@ static int mxvar_diagflag; static unsigned char mxser_msr[MXSER_PORTS + 1]; static struct mxser_mon_ext mon_data_ext; static int mxser_set_baud_method[MXSER_PORTS + 1]; -static spinlock_t gm_lock; #ifdef CONFIG_PCI -static int CheckIsMoxaMust(int io) +static int __devinit CheckIsMoxaMust(int io) { u8 oldmcr, hwid; int i; @@ -360,15 +370,6 @@ static void process_txrx_fifo(struct mxser_port *info) } } -static void mxser_do_softint(struct work_struct *work) -{ - struct mxser_port *info = container_of(work, struct mxser_port, tqueue); - struct tty_struct *tty = info->tty; - - if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) - tty_wakeup(tty); -} - static unsigned char mxser_get_msr(int baseaddr, int mode, int port) { unsigned char status = 0; @@ -456,10 +457,10 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, static int mxser_set_baud(struct mxser_port *info, long newspd) { + unsigned int i; int quot = 0; unsigned char cval; int ret = 0; - unsigned long flags; if (!info->tty || !info->tty->termios) return ret; @@ -471,29 +472,34 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) return 0; info->realbaud = newspd; - if (newspd == 134) { - quot = (2 * info->baud_base / 269); - } else if (newspd) { - quot = info->baud_base / newspd; - if (quot == 0) - quot = 1; + for (i = 0; i < BAUD_TABLE_NO; i++) + if (newspd == mxvar_baud_table[i]) + break; + if (i == BAUD_TABLE_NO) { + quot = info->baud_base / info->speed; + if (info->speed <= 0 || info->speed > info->max_baud) + quot = 0; } else { - quot = 0; + if (newspd == 134) { + quot = (2 * info->baud_base / 269); + } else if (newspd) { + quot = info->baud_base / newspd; + if (quot == 0) + quot = 1; + } else { + quot = 0; + } } info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); info->timeout += HZ / 50; /* Add .02 seconds of slop */ if (quot) { - spin_lock_irqsave(&info->slock, flags); info->MCR |= UART_MCR_DTR; outb(info->MCR, info->ioaddr + UART_MCR); - spin_unlock_irqrestore(&info->slock, flags); } else { - spin_lock_irqsave(&info->slock, flags); info->MCR &= ~UART_MCR_DTR; outb(info->MCR, info->ioaddr + UART_MCR); - spin_unlock_irqrestore(&info->slock, flags); return ret; } @@ -505,6 +511,18 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ + if (i == BAUD_TABLE_NO) { + quot = info->baud_base % info->speed; + quot *= 8; + if ((quot % info->speed) > (info->speed / 2)) { + quot /= info->speed; + quot++; + } else { + quot /= info->speed; + } + SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot); + } else + SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0); return ret; } @@ -520,7 +538,6 @@ static int mxser_change_speed(struct mxser_port *info, int ret = 0; unsigned char status; long baud; - unsigned long flags; if (!info->tty || !info->tty->termios) return ret; @@ -529,7 +546,10 @@ static int mxser_change_speed(struct mxser_port *info, return ret; if (mxser_set_baud_method[info->tty->index] == 0) { - baud = tty_get_baud_rate(info->tty); + if ((cflag & CBAUD) == B_SPEC) + baud = info->speed; + else + baud = tty_get_baud_rate(info->tty); mxser_set_baud(info, baud); } @@ -612,8 +632,8 @@ static int mxser_change_speed(struct mxser_port *info, outb(info->IER, info->ioaddr + UART_IER); } - set_bit(MXSER_EVENT_TXLOW, &info->event); - schedule_work(&info->tqueue); } + tty_wakeup(info->tty); + } } else { if (!(status & UART_MSR_CTS)) { info->tty->hw_stopped = 1; @@ -668,7 +688,6 @@ static int mxser_change_speed(struct mxser_port *info, } } if (info->board->chip_flag) { - spin_lock_irqsave(&info->slock, flags); SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); if (I_IXON(info->tty)) { @@ -681,7 +700,6 @@ static int mxser_change_speed(struct mxser_port *info, } else { DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); } - spin_unlock_irqrestore(&info->slock, flags); } @@ -708,7 +726,6 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { if (status & UART_MSR_DCD) wake_up_interruptible(&port->open_wait); - schedule_work(&port->tqueue); } if (port->flags & ASYNC_CTS_FLOW) { @@ -724,8 +741,7 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) outb(port->IER, port->ioaddr + UART_IER); } - set_bit(MXSER_EVENT_TXLOW, &port->event); - schedule_work(&port->tqueue); + tty_wakeup(port->tty); } } else { if (!(status & UART_MSR_CTS)) { @@ -836,10 +852,10 @@ static int mxser_startup(struct mxser_port *info) /* * and set the speed of the serial port */ - spin_unlock_irqrestore(&info->slock, flags); mxser_change_speed(info, NULL); - info->flags |= ASYNC_INITIALIZED; + spin_unlock_irqrestore(&info->slock, flags); + return 0; } @@ -909,11 +925,9 @@ static void mxser_shutdown(struct mxser_port *info) static int mxser_open(struct tty_struct *tty, struct file *filp) { struct mxser_port *info; + unsigned long flags; int retval, line; - /* initialize driver_data in case something fails */ - tty->driver_data = NULL; - line = tty->index; if (line == MXSER_PORTS) return 0; @@ -928,7 +942,9 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) /* * Start up serial port */ + spin_lock_irqsave(&info->slock, flags); info->count++; + spin_unlock_irqrestore(&info->slock, flags); retval = mxser_startup(info); if (retval) return retval; @@ -937,17 +953,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) if (retval) return retval; - if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver->subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->normal_termios; - else - *tty->termios = info->callout_termios; - mxser_change_speed(info, NULL); - } - - info->session = process_session(current); - info->pgrp = process_group(current); - /* unmark here for very high baud rate (ex. 921600 bps) used */ tty->low_latency = 1; return 0; @@ -1054,8 +1059,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) } info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - } static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) @@ -1222,6 +1225,7 @@ static int mxser_set_serial_info(struct mxser_port *info, struct serial_struct __user *new_info) { struct serial_struct new_serial; + unsigned long sl_flags; unsigned int flags; int retval = 0; @@ -1264,8 +1268,11 @@ static int mxser_set_serial_info(struct mxser_port *info, process_txrx_fifo(info); if (info->flags & ASYNC_INITIALIZED) { - if (flags != (info->flags & ASYNC_SPD_MASK)) + if (flags != (info->flags & ASYNC_SPD_MASK)) { + spin_lock_irqsave(&info->slock, sl_flags); mxser_change_speed(info, NULL); + spin_unlock_irqrestore(&info->slock, sl_flags); + } } else retval = mxser_startup(info); @@ -1373,11 +1380,10 @@ static int mxser_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int mxser_program_mode(int port) +static int __init mxser_program_mode(int port) { int id, i, j, n; - spin_lock(&gm_lock); outb(0, port); outb(0, port); outb(0, port); @@ -1385,7 +1391,6 @@ static int mxser_program_mode(int port) (void)inb(port); outb(0, port); (void)inb(port); - spin_unlock(&gm_lock); id = inb(port + 1) & 0x1F; if ((id != C168_ASIC_ID) && @@ -1410,7 +1415,7 @@ static int mxser_program_mode(int port) return id; } -static void mxser_normal_mode(int port) +static void __init mxser_normal_mode(int port) { int i, n; @@ -1443,7 +1448,7 @@ static void mxser_normal_mode(int port) #define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ #define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ #define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ -static int mxser_read_register(int port, unsigned short *regs) +static int __init mxser_read_register(int port, unsigned short *regs) { int i, k, value, id; unsigned int j; @@ -1644,6 +1649,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, struct serial_icounter_struct __user *p_cuser; unsigned long templ; unsigned long flags; + unsigned int i; void __user *argp = (void __user *)arg; int retval; @@ -1682,6 +1688,36 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return 0; } + if (cmd == MOXA_SET_SPECIAL_BAUD_RATE) { + int speed; + + if (get_user(speed, (int __user *)argp)) + return -EFAULT; + if (speed <= 0 || speed > info->max_baud) + return -EFAULT; + if (!info->tty || !info->tty->termios || !info->ioaddr) + return 0; + info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX); + for (i = 0; i < BAUD_TABLE_NO; i++) + if (speed == mxvar_baud_table[i]) + break; + if (i == BAUD_TABLE_NO) { + info->tty->termios->c_cflag |= B_SPEC; + } else if (speed != 0) + info->tty->termios->c_cflag |= mxvar_baud_table1[i]; + + info->speed = speed; + spin_lock_irqsave(&info->slock, flags); + mxser_change_speed(info, NULL); + spin_unlock_irqrestore(&info->slock, flags); + + return 0; + } else if (cmd == MOXA_GET_SPECIAL_BAUD_RATE) { + if (copy_to_user(argp, &info->speed, sizeof(int))) + return -EFAULT; + return 0; + } + if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && test_bit(TTY_IO_ERROR, &tty->flags)) return -EIO; @@ -1799,7 +1835,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, long baud; if (get_user(baud, (long __user *)argp)) return -EFAULT; + spin_lock_irqsave(&info->slock, flags); mxser_set_baud(info, baud); + spin_unlock_irqrestore(&info->slock, flags); return 0; } case MOXA_ASPP_GETBAUD: @@ -1976,7 +2014,9 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi if ((tty->termios->c_cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { + spin_lock_irqsave(&info->slock, flags); mxser_change_speed(info, old_termios); + spin_unlock_irqrestore(&info->slock, flags); if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { @@ -2066,7 +2106,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) /* * This routine is called by tty_hangup() when a hangup is signaled. */ -void mxser_hangup(struct tty_struct *tty) +static void mxser_hangup(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; @@ -2105,9 +2145,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) int cnt = 0; int recv_room; int max = 256; - unsigned long flags; - - spin_lock_irqsave(&port->slock, flags); recv_room = tty->receive_room; if ((recv_room == 0) && (!port->ldisc_stop_rx)) @@ -2169,7 +2206,8 @@ intr_old: } else if (*status & UART_LSR_OE) { flag = TTY_OVERRUN; port->icount.overrun++; - } + } else + flag = TTY_BREAK; } tty_insert_flip_char(tty, ch, flag); cnt++; @@ -2191,7 +2229,6 @@ end_intr: mxvar_log.rxcnt[port->tty->index] += cnt; port->mon_data.rxcnt += cnt; port->mon_data.up_rxcnt += cnt; - spin_unlock_irqrestore(&port->slock, flags); tty_flip_buffer_push(tty); } @@ -2199,9 +2236,6 @@ end_intr: static void mxser_transmit_chars(struct mxser_port *port) { int count, cnt; - unsigned long flags; - - spin_lock_irqsave(&port->slock, flags); if (port->x_char) { outb(port->x_char, port->ioaddr + UART_TX); @@ -2210,11 +2244,11 @@ static void mxser_transmit_chars(struct mxser_port *port) port->mon_data.txcnt++; port->mon_data.up_txcnt++; port->icount.tx++; - goto unlock; + return; } if (port->xmit_buf == 0) - goto unlock; + return; if ((port->xmit_cnt <= 0) || port->tty->stopped || (port->tty->hw_stopped && @@ -2222,7 +2256,7 @@ static void mxser_transmit_chars(struct mxser_port *port) (!port->board->chip_flag))) { port->IER &= ~UART_IER_THRI; outb(port->IER, port->ioaddr + UART_IER); - goto unlock; + return; } cnt = port->xmit_cnt; @@ -2240,16 +2274,13 @@ static void mxser_transmit_chars(struct mxser_port *port) port->mon_data.up_txcnt += (cnt - port->xmit_cnt); port->icount.tx += (cnt - port->xmit_cnt); - if (port->xmit_cnt < WAKEUP_CHARS) { - set_bit(MXSER_EVENT_TXLOW, &port->event); - schedule_work(&port->tqueue); - } + if (port->xmit_cnt < WAKEUP_CHARS) + tty_wakeup(port->tty); + if (port->xmit_cnt <= 0) { port->IER &= ~UART_IER_THRI; outb(port->IER, port->ioaddr + UART_IER); } -unlock: - spin_unlock_irqrestore(&port->slock, flags); } /* @@ -2261,8 +2292,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) struct mxser_board *brd = NULL; struct mxser_port *port; int max, irqbits, bits, msr; - int pass_counter = 0; - unsigned int int_cnt; + unsigned int int_cnt, pass_counter = 0; int handled = IRQ_NONE; for (i = 0; i < MXSER_BOARDS; i++) @@ -2276,7 +2306,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) if (brd == NULL) goto irq_stop; max = brd->info->nports; - while (1) { + while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { irqbits = inb(brd->vector) & brd->vector_mask; if (irqbits == brd->vector_mask) break; @@ -2290,12 +2320,16 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) port = &brd->ports[i]; int_cnt = 0; + spin_lock(&port->slock); do { iir = inb(port->ioaddr + UART_IIR); if (iir & UART_IIR_NO_INT) break; iir &= MOXA_MUST_IIR_MASK; - if (!port->tty) { + if (!port->tty || + (port->flags & ASYNC_CLOSING) || + !(port->flags & + ASYNC_INITIALIZED)) { status = inb(port->ioaddr + UART_LSR); outb(0x27, port->ioaddr + UART_FCR); inb(port->ioaddr + UART_MSR); @@ -2341,9 +2375,8 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) mxser_transmit_chars(port); } } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); + spin_unlock(&port->slock); } - if (pass_counter++ > MXSER_ISR_PASS_LIMIT) - break; /* Prevent infinite loops */ } irq_stop: @@ -2385,7 +2418,6 @@ static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, #ifdef CONFIG_PCI pci_release_region(pdev, 2); pci_release_region(pdev, 3); - pci_dev_put(pdev); #endif } else { release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); @@ -2420,11 +2452,10 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, info->custom_divisor = info->baud_base * 16; info->close_delay = 5 * HZ / 10; info->closing_wait = 30 * HZ; - INIT_WORK(&info->tqueue, mxser_do_softint); info->normal_termios = mxvar_sdriver->init_termios; init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); + info->speed = 9600; memset(&info->mon_data, 0, sizeof(struct mxser_mon)); info->err_shadow = 0; spin_lock_init(&info->slock); @@ -2433,22 +2464,17 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, outb(inb(info->ioaddr + UART_IER) & 0xf0, info->ioaddr + UART_IER); } - /* - * Allocate the IRQ if necessary - */ - retval = request_irq(brd->irq, mxser_interrupt, - (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : - IRQF_DISABLED, "mxser", brd); + retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", + brd); if (retval) { printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " "conflict with another device.\n", brd->info->name, brd->irq); /* We hold resources, we need to release them. */ mxser_release_res(brd, pdev, 0); - return retval; } - return 0; + return retval; } static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) @@ -2633,8 +2659,9 @@ static int __devinit mxser_probe(struct pci_dev *pdev, } /* mxser_initbrd will hook ISR. */ - if (mxser_initbrd(brd, pdev) < 0) - goto err_relvec; + retval = mxser_initbrd(brd, pdev); + if (retval) + goto err_null; for (i = 0; i < brd->info->nports; i++) tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); @@ -2642,10 +2669,9 @@ static int __devinit mxser_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, brd); return 0; -err_relvec: - pci_release_region(pdev, 3); err_relio: pci_release_region(pdev, 2); +err_null: brd->info = NULL; err: return retval; @@ -2663,6 +2689,7 @@ static void __devexit mxser_remove(struct pci_dev *pdev) tty_unregister_device(mxvar_sdriver, brd->idx + i); mxser_release_res(brd, pdev, 1); + brd->info = NULL; } static struct pci_driver mxser_driver = { @@ -2684,7 +2711,6 @@ static int __init mxser_module_init(void) mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); if (!mxvar_sdriver) return -ENOMEM; - spin_lock_init(&gm_lock); printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", MXSER_VERSION); diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h index a08f0ec..d42f776 100644 --- a/drivers/char/mxser_new.h +++ b/drivers/char/mxser_new.h @@ -26,18 +26,8 @@ #define RS422_MODE 2 #define RS485_4WIRE_MODE 3 #define OP_MODE_MASK 3 -// above add by Victor Yu. 01-05-2004 - -#define TTY_THRESHOLD_THROTTLE 128 - -#define LO_WATER (TTY_FLIPBUF_SIZE) -#define HI_WATER (TTY_FLIPBUF_SIZE*2*3/4) - -// added by James. 03-11-2004. -#define MOXA_SDS_GETICOUNTER (MOXA + 68) -#define MOXA_SDS_RSTICOUNTER (MOXA + 69) -// (above) added by James. +#define MOXA_SDS_RSTICOUNTER (MOXA + 69) #define MOXA_ASPP_OQUEUE (MOXA + 70) #define MOXA_ASPP_SETBAUD (MOXA + 71) #define MOXA_ASPP_GETBAUD (MOXA + 72) @@ -45,7 +35,8 @@ #define MOXA_ASPP_LSTATUS (MOXA + 74) #define MOXA_ASPP_MON_EXT (MOXA + 75) #define MOXA_SET_BAUD_METHOD (MOXA + 76) - +#define MOXA_SET_SPECIAL_BAUD_RATE (MOXA + 77) +#define MOXA_GET_SPECIAL_BAUD_RATE (MOXA + 78) /* --------------------------------------------------- */ @@ -55,51 +46,46 @@ #define NPPI_NOTIFY_SW_OVERRUN 0x08 #define NPPI_NOTIFY_BREAK 0x10 -#define NPPI_NOTIFY_CTSHOLD 0x01 // Tx hold by CTS low -#define NPPI_NOTIFY_DSRHOLD 0x02 // Tx hold by DSR low -#define NPPI_NOTIFY_XOFFHOLD 0x08 // Tx hold by Xoff received -#define NPPI_NOTIFY_XOFFXENT 0x10 // Xoff Sent - -//CheckIsMoxaMust return value -#define MOXA_OTHER_UART 0x00 -#define MOXA_MUST_MU150_HWID 0x01 -#define MOXA_MUST_MU860_HWID 0x02 - -// follow just for Moxa Must chip define. -// -// when LCR register (offset 0x03) write following value, -// the Must chip will enter enchance mode. And write value -// on EFR (offset 0x02) bit 6,7 to change bank. +#define NPPI_NOTIFY_CTSHOLD 0x01 /* Tx hold by CTS low */ +#define NPPI_NOTIFY_DSRHOLD 0x02 /* Tx hold by DSR low */ +#define NPPI_NOTIFY_XOFFHOLD 0x08 /* Tx hold by Xoff received */ +#define NPPI_NOTIFY_XOFFXENT 0x10 /* Xoff Sent */ + +/* follow just for Moxa Must chip define. */ +/* */ +/* when LCR register (offset 0x03) write following value, */ +/* the Must chip will enter enchance mode. And write value */ +/* on EFR (offset 0x02) bit 6,7 to change bank. */ #define MOXA_MUST_ENTER_ENCHANCE 0xBF -// when enhance mode enable, access on general bank register +/* when enhance mode enable, access on general bank register */ #define MOXA_MUST_GDL_REGISTER 0x07 #define MOXA_MUST_GDL_MASK 0x7F #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 -#define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO -// enchance register bank select and enchance mode setting register -// when LCR register equal to 0xBF +#define MOXA_MUST_LSR_RERR 0x80 /* error in receive FIFO */ +/* enchance register bank select and enchance mode setting register */ +/* when LCR register equal to 0xBF */ #define MOXA_MUST_EFR_REGISTER 0x02 -// enchance mode enable +/* enchance mode enable */ #define MOXA_MUST_EFR_EFRB_ENABLE 0x10 -// enchance reister bank set 0, 1, 2 +/* enchance reister bank set 0, 1, 2 */ #define MOXA_MUST_EFR_BANK0 0x00 #define MOXA_MUST_EFR_BANK1 0x40 #define MOXA_MUST_EFR_BANK2 0x80 #define MOXA_MUST_EFR_BANK3 0xC0 #define MOXA_MUST_EFR_BANK_MASK 0xC0 -// set XON1 value register, when LCR=0xBF and change to bank0 +/* set XON1 value register, when LCR=0xBF and change to bank0 */ #define MOXA_MUST_XON1_REGISTER 0x04 -// set XON2 value register, when LCR=0xBF and change to bank0 +/* set XON2 value register, when LCR=0xBF and change to bank0 */ #define MOXA_MUST_XON2_REGISTER 0x05 -// set XOFF1 value register, when LCR=0xBF and change to bank0 +/* set XOFF1 value register, when LCR=0xBF and change to bank0 */ #define MOXA_MUST_XOFF1_REGISTER 0x06 -// set XOFF2 value register, when LCR=0xBF and change to bank0 +/* set XOFF2 value register, when LCR=0xBF and change to bank0 */ #define MOXA_MUST_XOFF2_REGISTER 0x07 #define MOXA_MUST_RBRTL_REGISTER 0x04 @@ -111,32 +97,32 @@ #define MOXA_MUST_ECR_REGISTER 0x06 #define MOXA_MUST_CSR_REGISTER 0x07 -// good data mode enable +/* good data mode enable */ #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 -// only good data put into RxFIFO +/* only good data put into RxFIFO */ #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 -// enable CTS interrupt +/* enable CTS interrupt */ #define MOXA_MUST_IER_ECTSI 0x80 -// enable RTS interrupt +/* enable RTS interrupt */ #define MOXA_MUST_IER_ERTSI 0x40 -// enable Xon/Xoff interrupt +/* enable Xon/Xoff interrupt */ #define MOXA_MUST_IER_XINT 0x20 -// enable GDA interrupt +/* enable GDA interrupt */ #define MOXA_MUST_IER_EGDAI 0x10 #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) -// GDA interrupt pending +/* GDA interrupt pending */ #define MOXA_MUST_IIR_GDA 0x1C #define MOXA_MUST_IIR_RDA 0x04 #define MOXA_MUST_IIR_RTO 0x0C #define MOXA_MUST_IIR_LSR 0x06 -// recieved Xon/Xoff or specical interrupt pending +/* recieved Xon/Xoff or specical interrupt pending */ #define MOXA_MUST_IIR_XSC 0x10 -// RTS/CTS change state interrupt pending +/* RTS/CTS change state interrupt pending */ #define MOXA_MUST_IIR_RTSCTS 0x20 #define MOXA_MUST_IIR_MASK 0x3E @@ -144,307 +130,164 @@ #define MOXA_MUST_MCR_XON_ANY 0x80 #define MOXA_MUST_MCR_TX_XON 0x08 - -// software flow control on chip mask value +/* software flow control on chip mask value */ #define MOXA_MUST_EFR_SF_MASK 0x0F -// send Xon1/Xoff1 +/* send Xon1/Xoff1 */ #define MOXA_MUST_EFR_SF_TX1 0x08 -// send Xon2/Xoff2 +/* send Xon2/Xoff2 */ #define MOXA_MUST_EFR_SF_TX2 0x04 -// send Xon1,Xon2/Xoff1,Xoff2 +/* send Xon1,Xon2/Xoff1,Xoff2 */ #define MOXA_MUST_EFR_SF_TX12 0x0C -// don't send Xon/Xoff +/* don't send Xon/Xoff */ #define MOXA_MUST_EFR_SF_TX_NO 0x00 -// Tx software flow control mask +/* Tx software flow control mask */ #define MOXA_MUST_EFR_SF_TX_MASK 0x0C -// don't receive Xon/Xoff +/* don't receive Xon/Xoff */ #define MOXA_MUST_EFR_SF_RX_NO 0x00 -// receive Xon1/Xoff1 +/* receive Xon1/Xoff1 */ #define MOXA_MUST_EFR_SF_RX1 0x02 -// receive Xon2/Xoff2 +/* receive Xon2/Xoff2 */ #define MOXA_MUST_EFR_SF_RX2 0x01 -// receive Xon1,Xon2/Xoff1,Xoff2 +/* receive Xon1,Xon2/Xoff1,Xoff2 */ #define MOXA_MUST_EFR_SF_RX12 0x03 -// Rx software flow control mask +/* Rx software flow control mask */ #define MOXA_MUST_EFR_SF_RX_MASK 0x03 -//#define MOXA_MUST_MIN_XOFFLIMIT 66 -//#define MOXA_MUST_MIN_XONLIMIT 20 -//#define ID1_RX_TRIG 120 - - -#define CHECK_MOXA_MUST_XOFFLIMIT(info) { \ - if ( (info)->IsMoxaMustChipFlag && \ - (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \ - (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \ - (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \ - } \ -} - -#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ +#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK0; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) -#define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ +#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK0; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK0; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) -#define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK0; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -//#define MOXA_MUST_RBRL_VALUE 4 -#define SET_MOXA_MUST_FIFO_VALUE(info) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((info)->ioaddr+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR); \ +#define SET_MOXA_MUST_FIFO_VALUE(info) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((info)->ioaddr+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\ __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK1; \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ - outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER); \ - outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER); \ - outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER); \ - outb(__oldlcr, (info)->ioaddr+UART_LCR); \ -} - - - -#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + outb((u8)((info)->rx_high_water), (info)->ioaddr+ \ + MOXA_MUST_RBRTH_REGISTER); \ + outb((u8)((info)->rx_trigger), (info)->ioaddr+ \ + MOXA_MUST_RBRTI_REGISTER); \ + outb((u8)((info)->rx_low_water), (info)->ioaddr+ \ + MOXA_MUST_RBRTL_REGISTER); \ + outb(__oldlcr, (info)->ioaddr+UART_LCR); \ +} while (0) + +#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK2; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK2; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) -#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ - __efr |= MOXA_MUST_EFR_BANK2; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_MASK; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ +#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_MASK; \ - __efr |= MOXA_MUST_EFR_SF_TX1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK2; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ - __efr |= MOXA_MUST_EFR_SF_TX1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ + __efr |= MOXA_MUST_EFR_SF_TX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_MASK; \ - __efr |= MOXA_MUST_EFR_SF_RX1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ - __efr |= MOXA_MUST_EFR_SF_RX1; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ + __efr |= MOXA_MUST_EFR_SF_RX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) + +#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ - u8 __oldlcr, __efr; \ - __oldlcr = inb((baseio)+UART_LCR); \ - outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ - __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ - __efr &= ~MOXA_MUST_EFR_SF_MASK; \ - __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \ - outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ - outb(__oldlcr, (baseio)+UART_LCR); \ -} - -#define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ - u8 __oldmcr; \ - __oldmcr = inb((baseio)+UART_MCR); \ - __oldmcr |= MOXA_MUST_MCR_XON_ANY; \ - outb(__oldmcr, (baseio)+UART_MCR); \ -} - -#define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ - u8 __oldmcr; \ - __oldmcr = inb((baseio)+UART_MCR); \ - __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \ - outb(__oldmcr, (baseio)+UART_MCR); \ -} - -#define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) - - -#ifndef INIT_WORK -#define INIT_WORK(_work, _func, _data){ \ - _data->tqueue.routine = _func;\ - _data->tqueue.data = _data;\ - } -#endif + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} while (0) #endif diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index dc6d418..65f2d3a 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -60,62 +60,56 @@ #include <linux/slab.h> #include <linux/tty.h> #include <linux/errno.h> -#include <linux/string.h> /* used in new tty drivers */ -#include <linux/signal.h> /* used in new tty drivers */ +#include <linux/string.h> /* used in new tty drivers */ +#include <linux/signal.h> /* used in new tty drivers */ #include <linux/ioctl.h> #include <linux/n_r3964.h> #include <linux/poll.h> #include <linux/init.h> #include <asm/uaccess.h> - -//#define DEBUG_QUEUE +/*#define DEBUG_QUEUE*/ /* Log successful handshake and protocol operations */ -//#define DEBUG_PROTO_S +/*#define DEBUG_PROTO_S*/ /* Log handshake and protocol errors: */ -//#define DEBUG_PROTO_E +/*#define DEBUG_PROTO_E*/ /* Log Linediscipline operations (open, close, read, write...): */ -//#define DEBUG_LDISC +/*#define DEBUG_LDISC*/ /* Log module and memory operations (init, cleanup; kmalloc, kfree): */ -//#define DEBUG_MODUL +/*#define DEBUG_MODUL*/ /* Macro helpers for debug output: */ -#define TRACE(format, args...) printk("r3964: " format "\n" , ## args); +#define TRACE(format, args...) printk("r3964: " format "\n" , ## args) #ifdef DEBUG_MODUL -#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args); +#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args) #else -#define TRACE_M(fmt, arg...) /**/ +#define TRACE_M(fmt, arg...) do {} while (0) #endif - #ifdef DEBUG_PROTO_S -#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args); +#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args) #else -#define TRACE_PS(fmt, arg...) /**/ +#define TRACE_PS(fmt, arg...) do {} while (0) #endif - #ifdef DEBUG_PROTO_E -#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args); +#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args) #else -#define TRACE_PE(fmt, arg...) /**/ +#define TRACE_PE(fmt, arg...) do {} while (0) #endif - #ifdef DEBUG_LDISC -#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args); +#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args) #else -#define TRACE_L(fmt, arg...) /**/ +#define TRACE_L(fmt, arg...) do {} while (0) #endif - #ifdef DEBUG_QUEUE -#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args); +#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args) #else -#define TRACE_Q(fmt, arg...) /**/ +#define TRACE_Q(fmt, arg...) do {} while (0) #endif - static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); static void put_char(struct r3964_info *pInfo, unsigned char ch); @@ -126,937 +120,830 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c); static void receive_error(struct r3964_info *pInfo, const char flag); static void on_timeout(unsigned long priv); static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); -static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf); +static int read_telegram(struct r3964_info *pInfo, struct pid *pid, + unsigned char __user * buf); static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, - int error_code, struct r3964_block_header *pBlock); -static struct r3964_message* remove_msg(struct r3964_info *pInfo, - struct r3964_client_info *pClient); -static void remove_client_block(struct r3964_info *pInfo, - struct r3964_client_info *pClient); + int error_code, struct r3964_block_header *pBlock); +static struct r3964_message *remove_msg(struct r3964_info *pInfo, + struct r3964_client_info *pClient); +static void remove_client_block(struct r3964_info *pInfo, + struct r3964_client_info *pClient); -static int r3964_open(struct tty_struct *tty); +static int r3964_open(struct tty_struct *tty); static void r3964_close(struct tty_struct *tty); static ssize_t r3964_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr); -static ssize_t r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char * buf, size_t nr); -static int r3964_ioctl(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg); -static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); -static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, - struct poll_table_struct *wait); + unsigned char __user * buf, size_t nr); +static ssize_t r3964_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr); +static int r3964_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); +static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, + struct poll_table_struct *wait); static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count); + char *fp, int count); static struct tty_ldisc tty_ldisc_N_R3964 = { - .owner = THIS_MODULE, - .magic = TTY_LDISC_MAGIC, - .name = "R3964", - .open = r3964_open, - .close = r3964_close, - .read = r3964_read, - .write = r3964_write, - .ioctl = r3964_ioctl, + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "R3964", + .open = r3964_open, + .close = r3964_close, + .read = r3964_read, + .write = r3964_write, + .ioctl = r3964_ioctl, .set_termios = r3964_set_termios, - .poll = r3964_poll, + .poll = r3964_poll, .receive_buf = r3964_receive_buf, }; - - static void dump_block(const unsigned char *block, unsigned int length) { - unsigned int i,j; - char linebuf[16*3+1]; - - for(i=0;i<length;i+=16) - { - for(j=0;(j<16) && (j+i<length);j++) - { - sprintf(linebuf+3*j,"%02x ",block[i+j]); - } - linebuf[3*j]='\0'; - TRACE_PS("%s",linebuf); - } + unsigned int i, j; + char linebuf[16 * 3 + 1]; + + for (i = 0; i < length; i += 16) { + for (j = 0; (j < 16) && (j + i < length); j++) { + sprintf(linebuf + 3 * j, "%02x ", block[i + j]); + } + linebuf[3 * j] = '\0'; + TRACE_PS("%s", linebuf); + } } - - - /************************************************************* * Driver initialisation *************************************************************/ - /************************************************************* * Module support routines *************************************************************/ static void __exit r3964_exit(void) { - int status; - - TRACE_M ("cleanup_module()"); - - status=tty_unregister_ldisc(N_R3964); - - if(status!=0) - { - printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status); - } - else - { - TRACE_L("linediscipline successfully unregistered"); - } - + int status; + + TRACE_M("cleanup_module()"); + + status = tty_unregister_ldisc(N_R3964); + + if (status != 0) { + printk(KERN_ERR "r3964: error unregistering linediscipline: " + "%d\n", status); + } else { + TRACE_L("linediscipline successfully unregistered"); + } } static int __init r3964_init(void) { - int status; - - printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); - - /* - * Register the tty line discipline - */ - - status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964); - if (status == 0) - { - TRACE_L("line discipline %d registered", N_R3964); - TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, - tty_ldisc_N_R3964.num); - TRACE_L("open=%p", tty_ldisc_N_R3964.open); - TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); - } - else - { - printk (KERN_ERR "r3964: error registering line discipline: %d\n", status); - } - return status; + int status; + + printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); + + /* + * Register the tty line discipline + */ + + status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964); + if (status == 0) { + TRACE_L("line discipline %d registered", N_R3964); + TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, + tty_ldisc_N_R3964.num); + TRACE_L("open=%p", tty_ldisc_N_R3964.open); + TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); + } else { + printk(KERN_ERR "r3964: error registering line discipline: " + "%d\n", status); + } + return status; } module_init(r3964_init); module_exit(r3964_exit); - /************************************************************* * Protocol implementation routines *************************************************************/ -static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) +static void add_tx_queue(struct r3964_info *pInfo, + struct r3964_block_header *pHeader) { - unsigned long flags; - - spin_lock_irqsave(&pInfo->lock, flags); - - pHeader->next = NULL; - - if(pInfo->tx_last == NULL) - { - pInfo->tx_first = pInfo->tx_last = pHeader; - } - else - { - pInfo->tx_last->next = pHeader; - pInfo->tx_last = pHeader; - } - - spin_unlock_irqrestore(&pInfo->lock, flags); - - TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", - pHeader, pHeader->length, pInfo->tx_first ); + unsigned long flags; + + spin_lock_irqsave(&pInfo->lock, flags); + + pHeader->next = NULL; + + if (pInfo->tx_last == NULL) { + pInfo->tx_first = pInfo->tx_last = pHeader; + } else { + pInfo->tx_last->next = pHeader; + pInfo->tx_last = pHeader; + } + + spin_unlock_irqrestore(&pInfo->lock, flags); + + TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", + pHeader, pHeader->length, pInfo->tx_first); } static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) { - struct r3964_block_header *pHeader; - unsigned long flags; + struct r3964_block_header *pHeader; + unsigned long flags; #ifdef DEBUG_QUEUE - struct r3964_block_header *pDump; + struct r3964_block_header *pDump; #endif - - pHeader = pInfo->tx_first; - if(pHeader==NULL) - return; + pHeader = pInfo->tx_first; + + if (pHeader == NULL) + return; #ifdef DEBUG_QUEUE - printk("r3964: remove_from_tx_queue: %p, length %u - ", - pHeader, pHeader->length ); - for(pDump=pHeader;pDump;pDump=pDump->next) - printk("%p ", pDump); - printk("\n"); + printk("r3964: remove_from_tx_queue: %p, length %u - ", + pHeader, pHeader->length); + for (pDump = pHeader; pDump; pDump = pDump->next) + printk("%p ", pDump); + printk("\n"); #endif + if (pHeader->owner) { + if (error_code) { + add_msg(pHeader->owner, R3964_MSG_ACK, 0, + error_code, NULL); + } else { + add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, + error_code, NULL); + } + wake_up_interruptible(&pInfo->read_wait); + } + + spin_lock_irqsave(&pInfo->lock, flags); + + pInfo->tx_first = pHeader->next; + if (pInfo->tx_first == NULL) { + pInfo->tx_last = NULL; + } + + spin_unlock_irqrestore(&pInfo->lock, flags); + + kfree(pHeader); + TRACE_M("remove_from_tx_queue - kfree %p", pHeader); - if(pHeader->owner) - { - if(error_code) - { - add_msg(pHeader->owner, R3964_MSG_ACK, 0, - error_code, NULL); - } - else - { - add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, - error_code, NULL); - } - wake_up_interruptible (&pInfo->read_wait); - } - - spin_lock_irqsave(&pInfo->lock, flags); - - pInfo->tx_first = pHeader->next; - if(pInfo->tx_first==NULL) - { - pInfo->tx_last = NULL; - } - - spin_unlock_irqrestore(&pInfo->lock, flags); - - kfree(pHeader); - TRACE_M("remove_from_tx_queue - kfree %p",pHeader); - - TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", - pInfo->tx_first, pInfo->tx_last ); + TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", + pInfo->tx_first, pInfo->tx_last); } -static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) +static void add_rx_queue(struct r3964_info *pInfo, + struct r3964_block_header *pHeader) { - unsigned long flags; - - spin_lock_irqsave(&pInfo->lock, flags); - - pHeader->next = NULL; - - if(pInfo->rx_last == NULL) - { - pInfo->rx_first = pInfo->rx_last = pHeader; - } - else - { - pInfo->rx_last->next = pHeader; - pInfo->rx_last = pHeader; - } - pInfo->blocks_in_rx_queue++; - - spin_unlock_irqrestore(&pInfo->lock, flags); - - TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", - pHeader, pHeader->length, - pInfo->rx_first, pInfo->blocks_in_rx_queue); + unsigned long flags; + + spin_lock_irqsave(&pInfo->lock, flags); + + pHeader->next = NULL; + + if (pInfo->rx_last == NULL) { + pInfo->rx_first = pInfo->rx_last = pHeader; + } else { + pInfo->rx_last->next = pHeader; + pInfo->rx_last = pHeader; + } + pInfo->blocks_in_rx_queue++; + + spin_unlock_irqrestore(&pInfo->lock, flags); + + TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", + pHeader, pHeader->length, + pInfo->rx_first, pInfo->blocks_in_rx_queue); } static void remove_from_rx_queue(struct r3964_info *pInfo, - struct r3964_block_header *pHeader) + struct r3964_block_header *pHeader) { - unsigned long flags; - struct r3964_block_header *pFind; - - if(pHeader==NULL) - return; - - TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", - pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); - TRACE_Q("remove_from_rx_queue: %p, length %u", - pHeader, pHeader->length ); - - spin_lock_irqsave(&pInfo->lock, flags); - - if(pInfo->rx_first == pHeader) - { - /* Remove the first block in the linked list: */ - pInfo->rx_first = pHeader->next; - - if(pInfo->rx_first==NULL) - { - pInfo->rx_last = NULL; - } - pInfo->blocks_in_rx_queue--; - } - else - { - /* Find block to remove: */ - for(pFind=pInfo->rx_first; pFind; pFind=pFind->next) - { - if(pFind->next == pHeader) - { - /* Got it. */ - pFind->next = pHeader->next; - pInfo->blocks_in_rx_queue--; - if(pFind->next==NULL) - { - /* Oh, removed the last one! */ - pInfo->rx_last = pFind; - } - break; - } - } - } - - spin_unlock_irqrestore(&pInfo->lock, flags); - - kfree(pHeader); - TRACE_M("remove_from_rx_queue - kfree %p",pHeader); - - TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", - pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); + unsigned long flags; + struct r3964_block_header *pFind; + + if (pHeader == NULL) + return; + + TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", + pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); + TRACE_Q("remove_from_rx_queue: %p, length %u", + pHeader, pHeader->length); + + spin_lock_irqsave(&pInfo->lock, flags); + + if (pInfo->rx_first == pHeader) { + /* Remove the first block in the linked list: */ + pInfo->rx_first = pHeader->next; + + if (pInfo->rx_first == NULL) { + pInfo->rx_last = NULL; + } + pInfo->blocks_in_rx_queue--; + } else { + /* Find block to remove: */ + for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) { + if (pFind->next == pHeader) { + /* Got it. */ + pFind->next = pHeader->next; + pInfo->blocks_in_rx_queue--; + if (pFind->next == NULL) { + /* Oh, removed the last one! */ + pInfo->rx_last = pFind; + } + break; + } + } + } + + spin_unlock_irqrestore(&pInfo->lock, flags); + + kfree(pHeader); + TRACE_M("remove_from_rx_queue - kfree %p", pHeader); + + TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", + pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); } static void put_char(struct r3964_info *pInfo, unsigned char ch) { - struct tty_struct *tty = pInfo->tty; + struct tty_struct *tty = pInfo->tty; - if(tty==NULL) - return; + if (tty == NULL) + return; - if(tty->driver->put_char) - { - tty->driver->put_char(tty, ch); - } - pInfo->bcc ^= ch; + if (tty->driver->put_char) { + tty->driver->put_char(tty, ch); + } + pInfo->bcc ^= ch; } static void flush(struct r3964_info *pInfo) { - struct tty_struct *tty = pInfo->tty; + struct tty_struct *tty = pInfo->tty; - if(tty==NULL) - return; + if (tty == NULL) + return; - if(tty->driver->flush_chars) - { - tty->driver->flush_chars(tty); - } + if (tty->driver->flush_chars) { + tty->driver->flush_chars(tty); + } } static void trigger_transmit(struct r3964_info *pInfo) { - unsigned long flags; - + unsigned long flags; - spin_lock_irqsave(&pInfo->lock, flags); + spin_lock_irqsave(&pInfo->lock, flags); - if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL)) - { - pInfo->state = R3964_TX_REQUEST; - pInfo->nRetry=0; - pInfo->flags &= ~R3964_ERROR; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); + if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) { + pInfo->state = R3964_TX_REQUEST; + pInfo->nRetry = 0; + pInfo->flags &= ~R3964_ERROR; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); - spin_unlock_irqrestore(&pInfo->lock, flags); + spin_unlock_irqrestore(&pInfo->lock, flags); - TRACE_PS("trigger_transmit - sent STX"); + TRACE_PS("trigger_transmit - sent STX"); - put_char(pInfo, STX); - flush(pInfo); + put_char(pInfo, STX); + flush(pInfo); - pInfo->bcc = 0; - } - else - { - spin_unlock_irqrestore(&pInfo->lock, flags); - } + pInfo->bcc = 0; + } else { + spin_unlock_irqrestore(&pInfo->lock, flags); + } } static void retry_transmit(struct r3964_info *pInfo) { - if(pInfo->nRetry<R3964_MAX_RETRIES) - { - TRACE_PE("transmission failed. Retry #%d", - pInfo->nRetry); - pInfo->bcc = 0; - put_char(pInfo, STX); - flush(pInfo); - pInfo->state = R3964_TX_REQUEST; - pInfo->nRetry++; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); - } - else - { - TRACE_PE("transmission failed after %d retries", - R3964_MAX_RETRIES); - - remove_from_tx_queue(pInfo, R3964_TX_FAIL); - - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state = R3964_IDLE; - - trigger_transmit(pInfo); - } + if (pInfo->nRetry < R3964_MAX_RETRIES) { + TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry); + pInfo->bcc = 0; + put_char(pInfo, STX); + flush(pInfo); + pInfo->state = R3964_TX_REQUEST; + pInfo->nRetry++; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); + } else { + TRACE_PE("transmission failed after %d retries", + R3964_MAX_RETRIES); + + remove_from_tx_queue(pInfo, R3964_TX_FAIL); + + put_char(pInfo, NAK); + flush(pInfo); + pInfo->state = R3964_IDLE; + + trigger_transmit(pInfo); + } } - static void transmit_block(struct r3964_info *pInfo) { - struct tty_struct *tty = pInfo->tty; - struct r3964_block_header *pBlock = pInfo->tx_first; - int room=0; - - if((tty==NULL) || (pBlock==NULL)) - { - return; - } - - if(tty->driver->write_room) - room=tty->driver->write_room(tty); - - TRACE_PS("transmit_block %p, room %d, length %d", - pBlock, room, pBlock->length); - - while(pInfo->tx_position < pBlock->length) - { - if(room<2) - break; - - if(pBlock->data[pInfo->tx_position]==DLE) - { - /* send additional DLE char: */ - put_char(pInfo, DLE); - } - put_char(pInfo, pBlock->data[pInfo->tx_position++]); - - room--; - } - - if((pInfo->tx_position == pBlock->length) && (room>=3)) - { - put_char(pInfo, DLE); - put_char(pInfo, ETX); - if(pInfo->flags & R3964_BCC) - { - put_char(pInfo, pInfo->bcc); - } - pInfo->state = R3964_WAIT_FOR_TX_ACK; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); - } - flush(pInfo); + struct tty_struct *tty = pInfo->tty; + struct r3964_block_header *pBlock = pInfo->tx_first; + int room = 0; + + if ((tty == NULL) || (pBlock == NULL)) { + return; + } + + if (tty->driver->write_room) + room = tty->driver->write_room(tty); + + TRACE_PS("transmit_block %p, room %d, length %d", + pBlock, room, pBlock->length); + + while (pInfo->tx_position < pBlock->length) { + if (room < 2) + break; + + if (pBlock->data[pInfo->tx_position] == DLE) { + /* send additional DLE char: */ + put_char(pInfo, DLE); + } + put_char(pInfo, pBlock->data[pInfo->tx_position++]); + + room--; + } + + if ((pInfo->tx_position == pBlock->length) && (room >= 3)) { + put_char(pInfo, DLE); + put_char(pInfo, ETX); + if (pInfo->flags & R3964_BCC) { + put_char(pInfo, pInfo->bcc); + } + pInfo->state = R3964_WAIT_FOR_TX_ACK; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); + } + flush(pInfo); } static void on_receive_block(struct r3964_info *pInfo) { - unsigned int length; - struct r3964_client_info *pClient; - struct r3964_block_header *pBlock; - - length=pInfo->rx_position; - - /* compare byte checksum characters: */ - if(pInfo->flags & R3964_BCC) - { - if(pInfo->bcc!=pInfo->last_rx) - { - TRACE_PE("checksum error - got %x but expected %x", - pInfo->last_rx, pInfo->bcc); - pInfo->flags |= R3964_CHECKSUM; - } - } - - /* check for errors (parity, overrun,...): */ - if(pInfo->flags & R3964_ERROR) - { - TRACE_PE("on_receive_block - transmission failed error %x", - pInfo->flags & R3964_ERROR); - - put_char(pInfo, NAK); - flush(pInfo); - if(pInfo->nRetry<R3964_MAX_RETRIES) - { - pInfo->state=R3964_WAIT_FOR_RX_REPEAT; - pInfo->nRetry++; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); - } - else - { - TRACE_PE("on_receive_block - failed after max retries"); - pInfo->state=R3964_IDLE; - } - return; - } - - - /* received block; submit DLE: */ - put_char(pInfo, DLE); - flush(pInfo); - del_timer_sync(&pInfo->tmr); - TRACE_PS(" rx success: got %d chars", length); - - /* prepare struct r3964_block_header: */ - pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL); - TRACE_M("on_receive_block - kmalloc %p",pBlock); - - if(pBlock==NULL) - return; - - pBlock->length = length; - pBlock->data = ((unsigned char*)pBlock)+sizeof(struct r3964_block_header); - pBlock->locks = 0; - pBlock->next = NULL; - pBlock->owner = NULL; - - memcpy(pBlock->data, pInfo->rx_buf, length); - - /* queue block into rx_queue: */ - add_rx_queue(pInfo, pBlock); - - /* notify attached client processes: */ - for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) - { - if(pClient->sig_flags & R3964_SIG_DATA) - { - add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, pBlock); - } - } - wake_up_interruptible (&pInfo->read_wait); - - pInfo->state = R3964_IDLE; - - trigger_transmit(pInfo); -} + unsigned int length; + struct r3964_client_info *pClient; + struct r3964_block_header *pBlock; + + length = pInfo->rx_position; + + /* compare byte checksum characters: */ + if (pInfo->flags & R3964_BCC) { + if (pInfo->bcc != pInfo->last_rx) { + TRACE_PE("checksum error - got %x but expected %x", + pInfo->last_rx, pInfo->bcc); + pInfo->flags |= R3964_CHECKSUM; + } + } + + /* check for errors (parity, overrun,...): */ + if (pInfo->flags & R3964_ERROR) { + TRACE_PE("on_receive_block - transmission failed error %x", + pInfo->flags & R3964_ERROR); + + put_char(pInfo, NAK); + flush(pInfo); + if (pInfo->nRetry < R3964_MAX_RETRIES) { + pInfo->state = R3964_WAIT_FOR_RX_REPEAT; + pInfo->nRetry++; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); + } else { + TRACE_PE("on_receive_block - failed after max retries"); + pInfo->state = R3964_IDLE; + } + return; + } + + /* received block; submit DLE: */ + put_char(pInfo, DLE); + flush(pInfo); + del_timer_sync(&pInfo->tmr); + TRACE_PS(" rx success: got %d chars", length); + + /* prepare struct r3964_block_header: */ + pBlock = kmalloc(length + sizeof(struct r3964_block_header), + GFP_KERNEL); + TRACE_M("on_receive_block - kmalloc %p", pBlock); + + if (pBlock == NULL) + return; + + pBlock->length = length; + pBlock->data = ((unsigned char *)pBlock) + + sizeof(struct r3964_block_header); + pBlock->locks = 0; + pBlock->next = NULL; + pBlock->owner = NULL; + + memcpy(pBlock->data, pInfo->rx_buf, length); + + /* queue block into rx_queue: */ + add_rx_queue(pInfo, pBlock); + + /* notify attached client processes: */ + for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { + if (pClient->sig_flags & R3964_SIG_DATA) { + add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, + pBlock); + } + } + wake_up_interruptible(&pInfo->read_wait); + pInfo->state = R3964_IDLE; + + trigger_transmit(pInfo); +} static void receive_char(struct r3964_info *pInfo, const unsigned char c) { - switch(pInfo->state) - { - case R3964_TX_REQUEST: - if(c==DLE) - { - TRACE_PS("TX_REQUEST - got DLE"); - - pInfo->state = R3964_TRANSMITTING; - pInfo->tx_position = 0; - - transmit_block(pInfo); - } - else if(c==STX) - { - if(pInfo->nRetry==0) - { - TRACE_PE("TX_REQUEST - init conflict"); - if(pInfo->priority == R3964_SLAVE) - { - goto start_receiving; - } - } - else - { - TRACE_PE("TX_REQUEST - secondary init conflict!?" - " Switching to SLAVE mode for next rx."); - goto start_receiving; - } - } - else - { - TRACE_PE("TX_REQUEST - char != DLE: %x", c); - retry_transmit(pInfo); - } - break; - case R3964_TRANSMITTING: - if(c==NAK) - { - TRACE_PE("TRANSMITTING - got NAK"); - retry_transmit(pInfo); - } - else - { - TRACE_PE("TRANSMITTING - got invalid char"); - - pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - } - break; - case R3964_WAIT_FOR_TX_ACK: - if(c==DLE) - { - TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); - remove_from_tx_queue(pInfo, R3964_OK); - - pInfo->state = R3964_IDLE; - trigger_transmit(pInfo); - } - else - { - retry_transmit(pInfo); - } - break; - case R3964_WAIT_FOR_RX_REPEAT: - /* FALLTROUGH */ - case R3964_IDLE: - if(c==STX) - { - /* Prevent rx_queue from overflow: */ - if(pInfo->blocks_in_rx_queue >= R3964_MAX_BLOCKS_IN_RX_QUEUE) - { - TRACE_PE("IDLE - got STX but no space in rx_queue!"); - pInfo->state=R3964_WAIT_FOR_RX_BUF; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF); - break; - } + switch (pInfo->state) { + case R3964_TX_REQUEST: + if (c == DLE) { + TRACE_PS("TX_REQUEST - got DLE"); + + pInfo->state = R3964_TRANSMITTING; + pInfo->tx_position = 0; + + transmit_block(pInfo); + } else if (c == STX) { + if (pInfo->nRetry == 0) { + TRACE_PE("TX_REQUEST - init conflict"); + if (pInfo->priority == R3964_SLAVE) { + goto start_receiving; + } + } else { + TRACE_PE("TX_REQUEST - secondary init " + "conflict!? Switching to SLAVE mode " + "for next rx."); + goto start_receiving; + } + } else { + TRACE_PE("TX_REQUEST - char != DLE: %x", c); + retry_transmit(pInfo); + } + break; + case R3964_TRANSMITTING: + if (c == NAK) { + TRACE_PE("TRANSMITTING - got NAK"); + retry_transmit(pInfo); + } else { + TRACE_PE("TRANSMITTING - got invalid char"); + + pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); + } + break; + case R3964_WAIT_FOR_TX_ACK: + if (c == DLE) { + TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); + remove_from_tx_queue(pInfo, R3964_OK); + + pInfo->state = R3964_IDLE; + trigger_transmit(pInfo); + } else { + retry_transmit(pInfo); + } + break; + case R3964_WAIT_FOR_RX_REPEAT: + /* FALLTROUGH */ + case R3964_IDLE: + if (c == STX) { + /* Prevent rx_queue from overflow: */ + if (pInfo->blocks_in_rx_queue >= + R3964_MAX_BLOCKS_IN_RX_QUEUE) { + TRACE_PE("IDLE - got STX but no space in " + "rx_queue!"); + pInfo->state = R3964_WAIT_FOR_RX_BUF; + mod_timer(&pInfo->tmr, + jiffies + R3964_TO_NO_BUF); + break; + } start_receiving: - /* Ok, start receiving: */ - TRACE_PS("IDLE - got STX"); - pInfo->rx_position = 0; - pInfo->last_rx = 0; - pInfo->flags &= ~R3964_ERROR; - pInfo->state=R3964_RECEIVING; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - pInfo->nRetry = 0; - put_char(pInfo, DLE); - flush(pInfo); - pInfo->bcc = 0; - } - break; - case R3964_RECEIVING: - if(pInfo->rx_position < RX_BUF_SIZE) - { - pInfo->bcc ^= c; - - if(c==DLE) - { - if(pInfo->last_rx==DLE) - { - pInfo->last_rx = 0; - goto char_to_buf; - } - pInfo->last_rx = DLE; - break; - } - else if((c==ETX) && (pInfo->last_rx==DLE)) - { - if(pInfo->flags & R3964_BCC) - { - pInfo->state = R3964_WAIT_FOR_BCC; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - } - else - { - on_receive_block(pInfo); - } - } - else - { - pInfo->last_rx = c; + /* Ok, start receiving: */ + TRACE_PS("IDLE - got STX"); + pInfo->rx_position = 0; + pInfo->last_rx = 0; + pInfo->flags &= ~R3964_ERROR; + pInfo->state = R3964_RECEIVING; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); + pInfo->nRetry = 0; + put_char(pInfo, DLE); + flush(pInfo); + pInfo->bcc = 0; + } + break; + case R3964_RECEIVING: + if (pInfo->rx_position < RX_BUF_SIZE) { + pInfo->bcc ^= c; + + if (c == DLE) { + if (pInfo->last_rx == DLE) { + pInfo->last_rx = 0; + goto char_to_buf; + } + pInfo->last_rx = DLE; + break; + } else if ((c == ETX) && (pInfo->last_rx == DLE)) { + if (pInfo->flags & R3964_BCC) { + pInfo->state = R3964_WAIT_FOR_BCC; + mod_timer(&pInfo->tmr, + jiffies + R3964_TO_ZVZ); + } else { + on_receive_block(pInfo); + } + } else { + pInfo->last_rx = c; char_to_buf: - pInfo->rx_buf[pInfo->rx_position++] = c; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - } - } - /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ - break; - case R3964_WAIT_FOR_BCC: - pInfo->last_rx = c; - on_receive_block(pInfo); - break; - } + pInfo->rx_buf[pInfo->rx_position++] = c; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); + } + } + /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ + break; + case R3964_WAIT_FOR_BCC: + pInfo->last_rx = c; + on_receive_block(pInfo); + break; + } } static void receive_error(struct r3964_info *pInfo, const char flag) { - switch (flag) - { - case TTY_NORMAL: - break; - case TTY_BREAK: - TRACE_PE("received break") - pInfo->flags |= R3964_BREAK; - break; - case TTY_PARITY: - TRACE_PE("parity error") - pInfo->flags |= R3964_PARITY; - break; - case TTY_FRAME: - TRACE_PE("frame error") - pInfo->flags |= R3964_FRAME; - break; - case TTY_OVERRUN: - TRACE_PE("frame overrun") - pInfo->flags |= R3964_OVERRUN; - break; - default: - TRACE_PE("receive_error - unknown flag %d", flag); - pInfo->flags |= R3964_UNKNOWN; - break; - } + switch (flag) { + case TTY_NORMAL: + break; + case TTY_BREAK: + TRACE_PE("received break"); + pInfo->flags |= R3964_BREAK; + break; + case TTY_PARITY: + TRACE_PE("parity error"); + pInfo->flags |= R3964_PARITY; + break; + case TTY_FRAME: + TRACE_PE("frame error"); + pInfo->flags |= R3964_FRAME; + break; + case TTY_OVERRUN: + TRACE_PE("frame overrun"); + pInfo->flags |= R3964_OVERRUN; + break; + default: + TRACE_PE("receive_error - unknown flag %d", flag); + pInfo->flags |= R3964_UNKNOWN; + break; + } } static void on_timeout(unsigned long priv) { - struct r3964_info *pInfo = (void *)priv; - - switch(pInfo->state) - { - case R3964_TX_REQUEST: - TRACE_PE("TX_REQUEST - timeout"); - retry_transmit(pInfo); - break; - case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: - put_char(pInfo, NAK); - flush(pInfo); - retry_transmit(pInfo); - break; - case R3964_WAIT_FOR_TX_ACK: - TRACE_PE("WAIT_FOR_TX_ACK - timeout"); - retry_transmit(pInfo); - break; - case R3964_WAIT_FOR_RX_BUF: - TRACE_PE("WAIT_FOR_RX_BUF - timeout"); - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state=R3964_IDLE; - break; - case R3964_RECEIVING: - TRACE_PE("RECEIVING - timeout after %d chars", - pInfo->rx_position); - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state=R3964_IDLE; - break; - case R3964_WAIT_FOR_RX_REPEAT: - TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); - pInfo->state=R3964_IDLE; - break; - case R3964_WAIT_FOR_BCC: - TRACE_PE("WAIT_FOR_BCC - timeout"); - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state=R3964_IDLE; - break; - } + struct r3964_info *pInfo = (void *)priv; + + switch (pInfo->state) { + case R3964_TX_REQUEST: + TRACE_PE("TX_REQUEST - timeout"); + retry_transmit(pInfo); + break; + case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: + put_char(pInfo, NAK); + flush(pInfo); + retry_transmit(pInfo); + break; + case R3964_WAIT_FOR_TX_ACK: + TRACE_PE("WAIT_FOR_TX_ACK - timeout"); + retry_transmit(pInfo); + break; + case R3964_WAIT_FOR_RX_BUF: + TRACE_PE("WAIT_FOR_RX_BUF - timeout"); + put_char(pInfo, NAK); + flush(pInfo); + pInfo->state = R3964_IDLE; + break; + case R3964_RECEIVING: + TRACE_PE("RECEIVING - timeout after %d chars", + pInfo->rx_position); + put_char(pInfo, NAK); + flush(pInfo); + pInfo->state = R3964_IDLE; + break; + case R3964_WAIT_FOR_RX_REPEAT: + TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); + pInfo->state = R3964_IDLE; + break; + case R3964_WAIT_FOR_BCC: + TRACE_PE("WAIT_FOR_BCC - timeout"); + put_char(pInfo, NAK); + flush(pInfo); + pInfo->state = R3964_IDLE; + break; + } } -static struct r3964_client_info *findClient( - struct r3964_info *pInfo, struct pid *pid) +static struct r3964_client_info *findClient(struct r3964_info *pInfo, + struct pid *pid) { - struct r3964_client_info *pClient; - - for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) - { - if(pClient->pid == pid) - { - return pClient; - } - } - return NULL; + struct r3964_client_info *pClient; + + for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { + if (pClient->pid == pid) { + return pClient; + } + } + return NULL; } static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) { - struct r3964_client_info *pClient; - struct r3964_client_info **ppClient; - struct r3964_message *pMsg; - - if((arg & R3964_SIG_ALL)==0) - { - /* Remove client from client list */ - for(ppClient=&pInfo->firstClient; *ppClient; ppClient=&(*ppClient)->next) - { - pClient = *ppClient; - - if(pClient->pid == pid) - { - TRACE_PS("removing client %d from client list", pid_nr(pid)); - *ppClient = pClient->next; - while(pClient->msg_count) - { - pMsg=remove_msg(pInfo, pClient); - if(pMsg) - { - kfree(pMsg); - TRACE_M("enable_signals - msg kfree %p",pMsg); - } - } - put_pid(pClient->pid); - kfree(pClient); - TRACE_M("enable_signals - kfree %p",pClient); - return 0; - } - } - return -EINVAL; - } - else - { - pClient=findClient(pInfo, pid); - if(pClient) - { - /* update signal options */ - pClient->sig_flags=arg; - } - else - { - /* add client to client list */ - pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL); - TRACE_M("enable_signals - kmalloc %p",pClient); - if(pClient==NULL) - return -ENOMEM; - - TRACE_PS("add client %d to client list", pid_nr(pid)); - spin_lock_init(&pClient->lock); - pClient->sig_flags=arg; - pClient->pid = get_pid(pid); - pClient->next=pInfo->firstClient; - pClient->first_msg = NULL; - pClient->last_msg = NULL; - pClient->next_block_to_read = NULL; - pClient->msg_count = 0; - pInfo->firstClient=pClient; - } - } - - return 0; + struct r3964_client_info *pClient; + struct r3964_client_info **ppClient; + struct r3964_message *pMsg; + + if ((arg & R3964_SIG_ALL) == 0) { + /* Remove client from client list */ + for (ppClient = &pInfo->firstClient; *ppClient; + ppClient = &(*ppClient)->next) { + pClient = *ppClient; + + if (pClient->pid == pid) { + TRACE_PS("removing client %d from client list", + pid_nr(pid)); + *ppClient = pClient->next; + while (pClient->msg_count) { + pMsg = remove_msg(pInfo, pClient); + if (pMsg) { + kfree(pMsg); + TRACE_M("enable_signals - msg " + "kfree %p", pMsg); + } + } + put_pid(pClient->pid); + kfree(pClient); + TRACE_M("enable_signals - kfree %p", pClient); + return 0; + } + } + return -EINVAL; + } else { + pClient = findClient(pInfo, pid); + if (pClient) { + /* update signal options */ + pClient->sig_flags = arg; + } else { + /* add client to client list */ + pClient = kmalloc(sizeof(struct r3964_client_info), + GFP_KERNEL); + TRACE_M("enable_signals - kmalloc %p", pClient); + if (pClient == NULL) + return -ENOMEM; + + TRACE_PS("add client %d to client list", pid_nr(pid)); + spin_lock_init(&pClient->lock); + pClient->sig_flags = arg; + pClient->pid = get_pid(pid); + pClient->next = pInfo->firstClient; + pClient->first_msg = NULL; + pClient->last_msg = NULL; + pClient->next_block_to_read = NULL; + pClient->msg_count = 0; + pInfo->firstClient = pClient; + } + } + + return 0; } -static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf) +static int read_telegram(struct r3964_info *pInfo, struct pid *pid, + unsigned char __user * buf) { - struct r3964_client_info *pClient; - struct r3964_block_header *block; - - if(!buf) - { - return -EINVAL; - } - - pClient=findClient(pInfo,pid); - if(pClient==NULL) - { - return -EINVAL; - } - - block=pClient->next_block_to_read; - if(!block) - { - return 0; - } - else - { - if (copy_to_user (buf, block->data, block->length)) - return -EFAULT; - - remove_client_block(pInfo, pClient); - return block->length; - } - - return -EINVAL; + struct r3964_client_info *pClient; + struct r3964_block_header *block; + + if (!buf) { + return -EINVAL; + } + + pClient = findClient(pInfo, pid); + if (pClient == NULL) { + return -EINVAL; + } + + block = pClient->next_block_to_read; + if (!block) { + return 0; + } else { + if (copy_to_user(buf, block->data, block->length)) + return -EFAULT; + + remove_client_block(pInfo, pClient); + return block->length; + } + + return -EINVAL; } static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, - int error_code, struct r3964_block_header *pBlock) + int error_code, struct r3964_block_header *pBlock) { - struct r3964_message *pMsg; - unsigned long flags; - - if(pClient->msg_count<R3964_MAX_MSG_COUNT-1) - { + struct r3964_message *pMsg; + unsigned long flags; + + if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) { queue_the_message: - pMsg = kmalloc(sizeof(struct r3964_message), - error_code?GFP_ATOMIC:GFP_KERNEL); - TRACE_M("add_msg - kmalloc %p",pMsg); - if(pMsg==NULL) { - return; - } - - spin_lock_irqsave(&pClient->lock, flags); - - pMsg->msg_id = msg_id; - pMsg->arg = arg; - pMsg->error_code = error_code; - pMsg->block = pBlock; - pMsg->next = NULL; - - if(pClient->last_msg==NULL) - { - pClient->first_msg=pClient->last_msg=pMsg; - } - else - { - pClient->last_msg->next = pMsg; - pClient->last_msg=pMsg; - } - - pClient->msg_count++; - - if(pBlock!=NULL) - { - pBlock->locks++; - } - spin_unlock_irqrestore(&pClient->lock, flags); - } - else - { - if((pClient->last_msg->msg_id == R3964_MSG_ACK) - && (pClient->last_msg->error_code==R3964_OVERFLOW)) - { - pClient->last_msg->arg++; - TRACE_PE("add_msg - inc prev OVERFLOW-msg"); - } - else - { - msg_id = R3964_MSG_ACK; - arg = 0; - error_code = R3964_OVERFLOW; - pBlock = NULL; - TRACE_PE("add_msg - queue OVERFLOW-msg"); - goto queue_the_message; - } - } - /* Send SIGIO signal to client process: */ - if(pClient->sig_flags & R3964_USE_SIGIO) - { - kill_pid(pClient->pid, SIGIO, 1); - } + pMsg = kmalloc(sizeof(struct r3964_message), + error_code ? GFP_ATOMIC : GFP_KERNEL); + TRACE_M("add_msg - kmalloc %p", pMsg); + if (pMsg == NULL) { + return; + } + + spin_lock_irqsave(&pClient->lock, flags); + + pMsg->msg_id = msg_id; + pMsg->arg = arg; + pMsg->error_code = error_code; + pMsg->block = pBlock; + pMsg->next = NULL; + + if (pClient->last_msg == NULL) { + pClient->first_msg = pClient->last_msg = pMsg; + } else { + pClient->last_msg->next = pMsg; + pClient->last_msg = pMsg; + } + + pClient->msg_count++; + + if (pBlock != NULL) { + pBlock->locks++; + } + spin_unlock_irqrestore(&pClient->lock, flags); + } else { + if ((pClient->last_msg->msg_id == R3964_MSG_ACK) + && (pClient->last_msg->error_code == R3964_OVERFLOW)) { + pClient->last_msg->arg++; + TRACE_PE("add_msg - inc prev OVERFLOW-msg"); + } else { + msg_id = R3964_MSG_ACK; + arg = 0; + error_code = R3964_OVERFLOW; + pBlock = NULL; + TRACE_PE("add_msg - queue OVERFLOW-msg"); + goto queue_the_message; + } + } + /* Send SIGIO signal to client process: */ + if (pClient->sig_flags & R3964_USE_SIGIO) { + kill_pid(pClient->pid, SIGIO, 1); + } } static struct r3964_message *remove_msg(struct r3964_info *pInfo, - struct r3964_client_info *pClient) + struct r3964_client_info *pClient) { - struct r3964_message *pMsg=NULL; - unsigned long flags; - - if(pClient->first_msg) - { - spin_lock_irqsave(&pClient->lock, flags); - - pMsg = pClient->first_msg; - pClient->first_msg = pMsg->next; - if(pClient->first_msg==NULL) - { - pClient->last_msg = NULL; - } - - pClient->msg_count--; - if(pMsg->block) - { - remove_client_block(pInfo, pClient); - pClient->next_block_to_read = pMsg->block; - } - spin_unlock_irqrestore(&pClient->lock, flags); - } - return pMsg; + struct r3964_message *pMsg = NULL; + unsigned long flags; + + if (pClient->first_msg) { + spin_lock_irqsave(&pClient->lock, flags); + + pMsg = pClient->first_msg; + pClient->first_msg = pMsg->next; + if (pClient->first_msg == NULL) { + pClient->last_msg = NULL; + } + + pClient->msg_count--; + if (pMsg->block) { + remove_client_block(pInfo, pClient); + pClient->next_block_to_read = pMsg->block; + } + spin_unlock_irqrestore(&pClient->lock, flags); + } + return pMsg; } -static void remove_client_block(struct r3964_info *pInfo, - struct r3964_client_info *pClient) +static void remove_client_block(struct r3964_info *pInfo, + struct r3964_client_info *pClient) { - struct r3964_block_header *block; - - TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); - - block=pClient->next_block_to_read; - if(block) - { - block->locks--; - if(block->locks==0) - { - remove_from_rx_queue(pInfo, block); - } - } - pClient->next_block_to_read = NULL; -} + struct r3964_block_header *block; + + TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); + block = pClient->next_block_to_read; + if (block) { + block->locks--; + if (block->locks == 0) { + remove_from_rx_queue(pInfo, block); + } + } + pClient->next_block_to_read = NULL; +} /************************************************************* * Line discipline routines @@ -1064,342 +951,318 @@ static void remove_client_block(struct r3964_info *pInfo, static int r3964_open(struct tty_struct *tty) { - struct r3964_info *pInfo; - - TRACE_L("open"); - TRACE_L("tty=%p, PID=%d, disc_data=%p", - tty, current->pid, tty->disc_data); - - pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); - TRACE_M("r3964_open - info kmalloc %p",pInfo); - - if(!pInfo) - { - printk(KERN_ERR "r3964: failed to alloc info structure\n"); - return -ENOMEM; - } - - pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); - TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf); - - if(!pInfo->rx_buf) - { - printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); - kfree(pInfo); - TRACE_M("r3964_open - info kfree %p",pInfo); - return -ENOMEM; - } - - pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); - TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf); - - if(!pInfo->tx_buf) - { - printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); - kfree(pInfo->rx_buf); - TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf); - kfree(pInfo); - TRACE_M("r3964_open - info kfree %p",pInfo); - return -ENOMEM; - } - - spin_lock_init(&pInfo->lock); - pInfo->tty = tty; - init_waitqueue_head (&pInfo->read_wait); - pInfo->priority = R3964_MASTER; - pInfo->rx_first = pInfo->rx_last = NULL; - pInfo->tx_first = pInfo->tx_last = NULL; - pInfo->rx_position = 0; - pInfo->tx_position = 0; - pInfo->last_rx = 0; - pInfo->blocks_in_rx_queue = 0; - pInfo->firstClient=NULL; - pInfo->state=R3964_IDLE; - pInfo->flags = R3964_DEBUG; - pInfo->nRetry = 0; - - tty->disc_data = pInfo; - tty->receive_room = 65536; - - init_timer(&pInfo->tmr); - pInfo->tmr.data = (unsigned long)pInfo; - pInfo->tmr.function = on_timeout; - - return 0; + struct r3964_info *pInfo; + + TRACE_L("open"); + TRACE_L("tty=%p, PID=%d, disc_data=%p", + tty, current->pid, tty->disc_data); + + pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL); + TRACE_M("r3964_open - info kmalloc %p", pInfo); + + if (!pInfo) { + printk(KERN_ERR "r3964: failed to alloc info structure\n"); + return -ENOMEM; + } + + pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); + TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf); + + if (!pInfo->rx_buf) { + printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); + kfree(pInfo); + TRACE_M("r3964_open - info kfree %p", pInfo); + return -ENOMEM; + } + + pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); + TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf); + + if (!pInfo->tx_buf) { + printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); + kfree(pInfo->rx_buf); + TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf); + kfree(pInfo); + TRACE_M("r3964_open - info kfree %p", pInfo); + return -ENOMEM; + } + + spin_lock_init(&pInfo->lock); + pInfo->tty = tty; + init_waitqueue_head(&pInfo->read_wait); + pInfo->priority = R3964_MASTER; + pInfo->rx_first = pInfo->rx_last = NULL; + pInfo->tx_first = pInfo->tx_last = NULL; + pInfo->rx_position = 0; + pInfo->tx_position = 0; + pInfo->last_rx = 0; + pInfo->blocks_in_rx_queue = 0; + pInfo->firstClient = NULL; + pInfo->state = R3964_IDLE; + pInfo->flags = R3964_DEBUG; + pInfo->nRetry = 0; + + tty->disc_data = pInfo; + tty->receive_room = 65536; + + setup_timer(&pInfo->tmr, on_timeout, (unsigned long)pInfo); + + return 0; } static void r3964_close(struct tty_struct *tty) { - struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; - struct r3964_client_info *pClient, *pNext; - struct r3964_message *pMsg; - struct r3964_block_header *pHeader, *pNextHeader; - unsigned long flags; - - TRACE_L("close"); - - /* - * Make sure that our task queue isn't activated. If it - * is, take it out of the linked list. - */ - del_timer_sync(&pInfo->tmr); - - /* Remove client-structs and message queues: */ - pClient=pInfo->firstClient; - while(pClient) - { - pNext=pClient->next; - while(pClient->msg_count) - { - pMsg=remove_msg(pInfo, pClient); - if(pMsg) - { - kfree(pMsg); - TRACE_M("r3964_close - msg kfree %p",pMsg); - } - } - put_pid(pClient->pid); - kfree(pClient); - TRACE_M("r3964_close - client kfree %p",pClient); - pClient=pNext; - } - /* Remove jobs from tx_queue: */ - spin_lock_irqsave(&pInfo->lock, flags); - pHeader=pInfo->tx_first; - pInfo->tx_first=pInfo->tx_last=NULL; + struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; + struct r3964_client_info *pClient, *pNext; + struct r3964_message *pMsg; + struct r3964_block_header *pHeader, *pNextHeader; + unsigned long flags; + + TRACE_L("close"); + + /* + * Make sure that our task queue isn't activated. If it + * is, take it out of the linked list. + */ + del_timer_sync(&pInfo->tmr); + + /* Remove client-structs and message queues: */ + pClient = pInfo->firstClient; + while (pClient) { + pNext = pClient->next; + while (pClient->msg_count) { + pMsg = remove_msg(pInfo, pClient); + if (pMsg) { + kfree(pMsg); + TRACE_M("r3964_close - msg kfree %p", pMsg); + } + } + put_pid(pClient->pid); + kfree(pClient); + TRACE_M("r3964_close - client kfree %p", pClient); + pClient = pNext; + } + /* Remove jobs from tx_queue: */ + spin_lock_irqsave(&pInfo->lock, flags); + pHeader = pInfo->tx_first; + pInfo->tx_first = pInfo->tx_last = NULL; spin_unlock_irqrestore(&pInfo->lock, flags); - - while(pHeader) - { - pNextHeader=pHeader->next; - kfree(pHeader); - pHeader=pNextHeader; + + while (pHeader) { + pNextHeader = pHeader->next; + kfree(pHeader); + pHeader = pNextHeader; } - /* Free buffers: */ - wake_up_interruptible(&pInfo->read_wait); - kfree(pInfo->rx_buf); - TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf); - kfree(pInfo->tx_buf); - TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf); - kfree(pInfo); - TRACE_M("r3964_close - info kfree %p",pInfo); + /* Free buffers: */ + wake_up_interruptible(&pInfo->read_wait); + kfree(pInfo->rx_buf); + TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf); + kfree(pInfo->tx_buf); + TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf); + kfree(pInfo); + TRACE_M("r3964_close - info kfree %p", pInfo); } static ssize_t r3964_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) + unsigned char __user * buf, size_t nr) { - struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; - struct r3964_client_info *pClient; - struct r3964_message *pMsg; - struct r3964_client_message theMsg; - DECLARE_WAITQUEUE (wait, current); - - int count; - - TRACE_L("read()"); - - pClient=findClient(pInfo, task_pid(current)); - if(pClient) - { - pMsg = remove_msg(pInfo, pClient); - if(pMsg==NULL) - { - /* no messages available. */ - if (file->f_flags & O_NONBLOCK) - { - return -EAGAIN; - } - /* block until there is a message: */ - add_wait_queue(&pInfo->read_wait, &wait); + struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; + struct r3964_client_info *pClient; + struct r3964_message *pMsg; + struct r3964_client_message theMsg; + DECLARE_WAITQUEUE(wait, current); + + int count; + + TRACE_L("read()"); + + pClient = findClient(pInfo, task_pid(current)); + if (pClient) { + pMsg = remove_msg(pInfo, pClient); + if (pMsg == NULL) { + /* no messages available. */ + if (file->f_flags & O_NONBLOCK) { + return -EAGAIN; + } + /* block until there is a message: */ + add_wait_queue(&pInfo->read_wait, &wait); repeat: - current->state = TASK_INTERRUPTIBLE; - pMsg = remove_msg(pInfo, pClient); - if (!pMsg && !signal_pending(current)) - { - schedule(); - goto repeat; - } - current->state = TASK_RUNNING; - remove_wait_queue(&pInfo->read_wait, &wait); - } - - /* If we still haven't got a message, we must have been signalled */ - - if (!pMsg) return -EINTR; - - /* deliver msg to client process: */ - theMsg.msg_id = pMsg->msg_id; - theMsg.arg = pMsg->arg; - theMsg.error_code = pMsg->error_code; - count = sizeof(struct r3964_client_message); - - kfree(pMsg); - TRACE_M("r3964_read - msg kfree %p",pMsg); - - if (copy_to_user(buf,&theMsg, count)) - return -EFAULT; - - TRACE_PS("read - return %d", count); - return count; - } - return -EPERM; + current->state = TASK_INTERRUPTIBLE; + pMsg = remove_msg(pInfo, pClient); + if (!pMsg && !signal_pending(current)) { + schedule(); + goto repeat; + } + current->state = TASK_RUNNING; + remove_wait_queue(&pInfo->read_wait, &wait); + } + + /* If we still haven't got a message, we must have been signalled */ + + if (!pMsg) + return -EINTR; + + /* deliver msg to client process: */ + theMsg.msg_id = pMsg->msg_id; + theMsg.arg = pMsg->arg; + theMsg.error_code = pMsg->error_code; + count = sizeof(struct r3964_client_message); + + kfree(pMsg); + TRACE_M("r3964_read - msg kfree %p", pMsg); + + if (copy_to_user(buf, &theMsg, count)) + return -EFAULT; + + TRACE_PS("read - return %d", count); + return count; + } + return -EPERM; } -static ssize_t r3964_write(struct tty_struct * tty, struct file * file, +static ssize_t r3964_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count) { - struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; - struct r3964_block_header *pHeader; - struct r3964_client_info *pClient; - unsigned char *new_data; - - TRACE_L("write request, %d characters", count); + struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; + struct r3964_block_header *pHeader; + struct r3964_client_info *pClient; + unsigned char *new_data; + + TRACE_L("write request, %d characters", count); /* * Verify the pointers */ - if(!pInfo) - return -EIO; + if (!pInfo) + return -EIO; /* * Ensure that the caller does not wish to send too much. */ - if (count > R3964_MTU) - { - if (pInfo->flags & R3964_DEBUG) - { - TRACE_L (KERN_WARNING - "r3964_write: truncating user packet " - "from %u to mtu %d", count, R3964_MTU); - } - count = R3964_MTU; - } + if (count > R3964_MTU) { + if (pInfo->flags & R3964_DEBUG) { + TRACE_L(KERN_WARNING "r3964_write: truncating user " + "packet from %u to mtu %d", count, R3964_MTU); + } + count = R3964_MTU; + } /* * Allocate a buffer for the data and copy it from the buffer with header prepended */ - new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); - TRACE_M("r3964_write - kmalloc %p",new_data); - if (new_data == NULL) { - if (pInfo->flags & R3964_DEBUG) - { - printk (KERN_ERR - "r3964_write: no memory\n"); - } - return -ENOSPC; - } - - pHeader = (struct r3964_block_header *)new_data; - pHeader->data = new_data + sizeof(struct r3964_block_header); - pHeader->length = count; - pHeader->locks = 0; - pHeader->owner = NULL; - - pClient=findClient(pInfo, task_pid(current)); - if(pClient) - { - pHeader->owner = pClient; - } - - memcpy(pHeader->data, data, count); /* We already verified this */ - - if(pInfo->flags & R3964_DEBUG) - { - dump_block(pHeader->data, count); - } + new_data = kmalloc(count + sizeof(struct r3964_block_header), + GFP_KERNEL); + TRACE_M("r3964_write - kmalloc %p", new_data); + if (new_data == NULL) { + if (pInfo->flags & R3964_DEBUG) { + printk(KERN_ERR "r3964_write: no memory\n"); + } + return -ENOSPC; + } + + pHeader = (struct r3964_block_header *)new_data; + pHeader->data = new_data + sizeof(struct r3964_block_header); + pHeader->length = count; + pHeader->locks = 0; + pHeader->owner = NULL; + + pClient = findClient(pInfo, task_pid(current)); + if (pClient) { + pHeader->owner = pClient; + } + + memcpy(pHeader->data, data, count); /* We already verified this */ + + if (pInfo->flags & R3964_DEBUG) { + dump_block(pHeader->data, count); + } /* * Add buffer to transmit-queue: */ - add_tx_queue(pInfo, pHeader); - trigger_transmit(pInfo); - - return 0; + add_tx_queue(pInfo, pHeader); + trigger_transmit(pInfo); + + return 0; } -static int r3964_ioctl(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg) +static int r3964_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { - struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; - if(pInfo==NULL) - return -EINVAL; - switch(cmd) - { - case R3964_ENABLE_SIGNALS: - return enable_signals(pInfo, task_pid(current), arg); - case R3964_SETPRIORITY: - if(arg<R3964_MASTER || arg>R3964_SLAVE) - return -EINVAL; - pInfo->priority = arg & 0xff; - return 0; - case R3964_USE_BCC: - if(arg) - pInfo->flags |= R3964_BCC; - else - pInfo->flags &= ~R3964_BCC; - return 0; - case R3964_READ_TELEGRAM: - return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg); - default: - return -ENOIOCTLCMD; - } + struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; + if (pInfo == NULL) + return -EINVAL; + switch (cmd) { + case R3964_ENABLE_SIGNALS: + return enable_signals(pInfo, task_pid(current), arg); + case R3964_SETPRIORITY: + if (arg < R3964_MASTER || arg > R3964_SLAVE) + return -EINVAL; + pInfo->priority = arg & 0xff; + return 0; + case R3964_USE_BCC: + if (arg) + pInfo->flags |= R3964_BCC; + else + pInfo->flags &= ~R3964_BCC; + return 0; + case R3964_READ_TELEGRAM: + return read_telegram(pInfo, task_pid(current), + (unsigned char __user *)arg); + default: + return -ENOIOCTLCMD; + } } -static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) +static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) { - TRACE_L("set_termios"); + TRACE_L("set_termios"); } /* Called without the kernel lock held - fine */ -static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, - struct poll_table_struct *wait) +static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, + struct poll_table_struct *wait) { - struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; - struct r3964_client_info *pClient; - struct r3964_message *pMsg=NULL; - unsigned long flags; - int result = POLLOUT; - - TRACE_L("POLL"); - - pClient=findClient(pInfo, task_pid(current)); - if(pClient) - { - poll_wait(file, &pInfo->read_wait, wait); - spin_lock_irqsave(&pInfo->lock, flags); - pMsg=pClient->first_msg; - spin_unlock_irqrestore(&pInfo->lock, flags); - if(pMsg) - result |= POLLIN | POLLRDNORM; - } - else - { - result = -EINVAL; - } - return result; + struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; + struct r3964_client_info *pClient; + struct r3964_message *pMsg = NULL; + unsigned long flags; + int result = POLLOUT; + + TRACE_L("POLL"); + + pClient = findClient(pInfo, task_pid(current)); + if (pClient) { + poll_wait(file, &pInfo->read_wait, wait); + spin_lock_irqsave(&pInfo->lock, flags); + pMsg = pClient->first_msg; + spin_unlock_irqrestore(&pInfo->lock, flags); + if (pMsg) + result |= POLLIN | POLLRDNORM; + } else { + result = -EINVAL; + } + return result; } static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + char *fp, int count) { - struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; - const unsigned char *p; - char *f, flags = 0; - int i; - - for (i=count, p = cp, f = fp; i; i--, p++) { - if (f) - flags = *f++; - if(flags==TTY_NORMAL) - { - receive_char(pInfo, *p); - } - else - { - receive_error(pInfo, flags); - } - - } + struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; + const unsigned char *p; + char *f, flags = 0; + int i; + + for (i = count, p = cp, f = fp; i; i--, p++) { + if (f) + flags = *f++; + if (flags == TTY_NORMAL) { + receive_char(pInfo, *p); + } else { + receive_error(pInfo, flags); + } + + } } MODULE_LICENSE("GPL"); diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 2bdb014..6ac3ca4 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -579,8 +579,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) static inline void isig(int sig, struct tty_struct *tty, int flush) { - if (tty->pgrp > 0) - kill_pg(tty->pgrp, sig, 1); + if (tty->pgrp) + kill_pgrp(tty->pgrp, sig, 1); if (flush || !L_NOFLSH(tty)) { n_tty_flush_buffer(tty); if (tty->driver->flush_buffer) @@ -1184,13 +1184,13 @@ static int job_control(struct tty_struct *tty, struct file *file) /* don't stop on /dev/console */ if (file->f_op->write != redirected_tty_write && current->signal->tty == tty) { - if (tty->pgrp <= 0) - printk("read_chan: tty->pgrp <= 0!\n"); - else if (process_group(current) != tty->pgrp) { + if (!tty->pgrp) + printk("read_chan: no tty->pgrp!\n"); + else if (task_pgrp(current) != tty->pgrp) { if (is_ignored(SIGTTIN) || - is_orphaned_pgrp(process_group(current))) + is_current_pgrp_orphaned()) return -EIO; - kill_pg(process_group(current), SIGTTIN, 1); + kill_pgrp(task_pgrp(current), SIGTTIN, 1); return -ERESTARTSYS; } } diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 2d26497..2604246 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -23,8 +23,11 @@ #define __NWBUTTON_C /* Tell the header file who we are */ #include "nwbutton.h" +static void button_sequence_finished (unsigned long parameters); + static int button_press_count; /* The count of button presses */ -static struct timer_list button_timer; /* Times for the end of a sequence */ +/* Times for the end of a sequence */ +static DEFINE_TIMER(button_timer, button_sequence_finished, 0, 0); static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue); /* Used for blocking read */ static char button_output_buffer[32]; /* Stores data to write out of device */ static int bcount; /* The number of bytes in the buffer */ @@ -146,14 +149,8 @@ static void button_sequence_finished (unsigned long parameters) static irqreturn_t button_handler (int irq, void *dev_id) { - if (button_press_count) { - del_timer (&button_timer); - } button_press_count++; - init_timer (&button_timer); - button_timer.function = button_sequence_finished; - button_timer.expires = (jiffies + bdelay); - add_timer (&button_timer); + mod_timer(&button_timer, jiffies + bdelay); return IRQ_HANDLED; } diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 211c93f..e91b43a 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -946,8 +946,7 @@ release_io: return_with_timer: DEBUGP(7, dev, "<- monitor_card (returns with timer)\n"); - dev->timer.expires = jiffies + dev->mdelay; - add_timer(&dev->timer); + mod_timer(&dev->timer, jiffies + dev->mdelay); clear_bit(LOCK_MONITOR, &dev->flags); } @@ -1406,12 +1405,9 @@ static void start_monitor(struct cm4000_dev *dev) DEBUGP(3, dev, "-> start_monitor\n"); if (!dev->monitor_running) { DEBUGP(5, dev, "create, init and add timer\n"); - init_timer(&dev->timer); + setup_timer(&dev->timer, monitor_card, (unsigned long)dev); dev->monitor_running = 1; - dev->timer.expires = jiffies; - dev->timer.data = (unsigned long) dev; - dev->timer.function = monitor_card; - add_timer(&dev->timer); + mod_timer(&dev->timer, jiffies); } else DEBUGP(5, dev, "monitor already running\n"); DEBUGP(3, dev, "<- start_monitor\n"); diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 9b1ff7e..0e82968 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -632,8 +632,7 @@ static int reader_probe(struct pcmcia_device *link) init_waitqueue_head(&dev->poll_wait); init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->write_wait); - init_timer(&dev->poll_timer); - dev->poll_timer.function = &cm4040_do_poll; + setup_timer(&dev->poll_timer, cm4040_do_poll, 0); ret = reader_config(link, i); if (ret) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index f108c13..8d025e9 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -887,10 +887,8 @@ static void bh_transmit(MGSLPC_INFO *info) if (debug_level >= DEBUG_LEVEL_BH) printk("bh_transmit() entry on %s\n", info->device_name); - if (tty) { + if (tty) tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } } static void bh_status(MGSLPC_INFO *info) @@ -1363,9 +1361,7 @@ static int startup(MGSLPC_INFO * info) memset(&info->icount, 0, sizeof(info->icount)); - init_timer(&info->tx_timer); - info->tx_timer.data = (unsigned long)info; - info->tx_timer.function = tx_timeout; + setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); /* Allocate and claim adapter resources */ retval = claim_resources(info); @@ -1410,7 +1406,7 @@ static void shutdown(MGSLPC_INFO * info) wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); - del_timer(&info->tx_timer); + del_timer_sync(&info->tx_timer); if (info->tx_buf) { free_page((unsigned long) info->tx_buf); @@ -3551,8 +3547,8 @@ static void tx_start(MGSLPC_INFO *info) } else { info->tx_active = 1; tx_ready(info); - info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); - add_timer(&info->tx_timer); + mod_timer(&info->tx_timer, jiffies + + msecs_to_jiffies(5000)); } } diff --git a/drivers/char/random.c b/drivers/char/random.c index 13d0b13..b9dc7aa 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1117,14 +1117,14 @@ random_ioctl(struct inode * inode, struct file * file, } } -struct file_operations random_fops = { +const struct file_operations random_fops = { .read = random_read, .write = random_write, .poll = random_poll, .ioctl = random_ioctl, }; -struct file_operations urandom_fops = { +const struct file_operations urandom_fops = { .read = urandom_read, .write = random_write, .ioctl = random_ioctl, diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 645e20a..1f0d7c6 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -154,7 +154,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, goto out; } - if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) { + if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) { err = -EINVAL; goto out; } diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index e79b2ed..85c1618 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -418,8 +418,7 @@ static void rio_pollfunc(unsigned long data) func_enter(); rio_interrupt(0, &p->RIOHosts[data]); - p->RIOHosts[data].timer.expires = jiffies + rio_poll; - add_timer(&p->RIOHosts[data].timer); + mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll); func_exit(); } @@ -1154,13 +1153,10 @@ static int __init rio_init(void) /* Init the timer "always" to make sure that it can safely be deleted when we unload... */ - init_timer(&hp->timer); + setup_timer(&hp->timer, rio_pollfunc, i); if (!hp->Ivec) { rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll); - hp->timer.data = i; - hp->timer.function = rio_pollfunc; - hp->timer.expires = jiffies + rio_poll; - add_timer(&hp->timer); + mod_timer(&hp->timer, jiffies + rio_poll); } } @@ -1191,7 +1187,7 @@ static void __exit rio_exit(void) rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); } /* It is safe/allowed to del_timer a non-active timer */ - del_timer(&hp->timer); + del_timer_sync(&hp->timer); if (hp->Caddr) iounmap(hp->Caddr); if (hp->Type == RIO_PCI) diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c index eeda40c..ebc7634 100644 --- a/drivers/char/rio/riointr.c +++ b/drivers/char/rio/riointr.c @@ -162,13 +162,8 @@ void RIOTxEnable(char *en) rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) { - rio_dprintk(RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", (int) (PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); - if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && PortP->gs.tty->ldisc.write_wakeup) - (PortP->gs.tty->ldisc.write_wakeup) (PortP->gs.tty); - rio_dprintk(RIO_DEBUG_INTR, "(%d/%d)\n", PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); - wake_up_interruptible(&PortP->gs.tty->write_wait); - } + if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) + tty_wakeup(PortP->gs.tty); } diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index e2a94bf..7014525 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1229,7 +1229,6 @@ static void rc_flush_buffer(struct tty_struct *tty) port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; restore_flags(flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -1570,10 +1569,8 @@ static void do_softint(struct work_struct *ugly_api) if(!(tty = port->tty)) return; - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } } static const struct tty_operations riscom_ops = { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index e94a62e..76357c8 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -106,6 +106,8 @@ /****** RocketPort Local Variables ******/ +static void rp_do_poll(unsigned long dummy); + static struct tty_driver *rocket_driver; static struct rocket_version driver_version = { @@ -116,7 +118,7 @@ static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */ /* eg. Bit 0 indicates port 0 has xmit data, ... */ static atomic_t rp_num_ports_open; /* Number of serial ports open */ -static struct timer_list rocket_timer; +static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0); static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */ static unsigned long board2; @@ -474,7 +476,6 @@ static void rp_do_transmit(struct r_port *info) if (info->xmit_cnt < WAKEUP_CHARS) { tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); #ifdef ROCKETPORT_HAVE_POLL_WAIT wake_up_interruptible(&tty->poll_wait); #endif @@ -1772,7 +1773,6 @@ static int rp_write(struct tty_struct *tty, end: if (info->xmit_cnt < WAKEUP_CHARS) { tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); #ifdef ROCKETPORT_HAVE_POLL_WAIT wake_up_interruptible(&tty->poll_wait); #endif @@ -1841,7 +1841,6 @@ static void rp_flush_buffer(struct tty_struct *tty) info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; spin_unlock_irqrestore(&info->slock, flags); - wake_up_interruptible(&tty->write_wait); #ifdef ROCKETPORT_HAVE_POLL_WAIT wake_up_interruptible(&tty->poll_wait); #endif @@ -2371,12 +2370,6 @@ static int __init rp_init(void) return -ENOMEM; /* - * Set up the timer channel. - */ - init_timer(&rocket_timer); - rocket_timer.function = rp_do_poll; - - /* * Initialize the array of pointers to our own internal state * structures. */ diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 664f36c..b6d3072d 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -135,7 +135,9 @@ static struct fasync_struct *rtc_async_queue; static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); #ifdef RTC_IRQ -static struct timer_list rtc_irq_timer; +static void rtc_dropped_irq(unsigned long data); + +static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0); #endif static ssize_t rtc_read(struct file *file, char __user *buf, @@ -150,8 +152,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait); static void get_rtc_alm_time (struct rtc_time *alm_tm); #ifdef RTC_IRQ -static void rtc_dropped_irq(unsigned long data); - static void set_rtc_irq_bit_locked(unsigned char bit); static void mask_rtc_irq_bit_locked(unsigned char bit); @@ -454,8 +454,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) spin_lock_irqsave (&rtc_lock, flags); if (!(rtc_status & RTC_TIMER_ON)) { - rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; - add_timer(&rtc_irq_timer); + mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + + 2*HZ/100); rtc_status |= RTC_TIMER_ON; } set_rtc_irq_bit_locked(RTC_PIE); @@ -1084,8 +1084,6 @@ no_irq: if (rtc_has_irq == 0) goto no_irq2; - init_timer(&rtc_irq_timer); - rtc_irq_timer.function = rtc_dropped_irq; spin_lock_irq(&rtc_lock); rtc_freq = 1024; if (!hpet_set_periodic_freq(rtc_freq)) { diff --git a/drivers/char/scan_keyb.c b/drivers/char/scan_keyb.c deleted file mode 100644 index 2b5bb4f..0000000 --- a/drivers/char/scan_keyb.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $ - * Copyright (C) 2000 YAEGASHI Takeshi - * Generic scan keyboard driver - */ - -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/tty.h> -#include <linux/mm.h> -#include <linux/signal.h> -#include <linux/init.h> -#include <linux/kbd_ll.h> -#include <linux/delay.h> -#include <linux/random.h> -#include <linux/poll.h> -#include <linux/miscdevice.h> -#include <linux/slab.h> -#include <linux/kbd_kern.h> -#include <linux/timer.h> - -#define SCANHZ (HZ/20) - -struct scan_keyboard { - struct scan_keyboard *next; - int (*scan)(unsigned char *buffer); - const unsigned char *table; - unsigned char *s0, *s1; - int length; -}; - -static int scan_jiffies=0; -static struct scan_keyboard *keyboards=NULL; -struct timer_list scan_timer; - -static void check_kbd(const unsigned char *table, - unsigned char *new, unsigned char *old, int length) -{ - int need_tasklet_schedule=0; - unsigned int xor, bit; - - while(length-->0) { - if((xor=*new^*old)==0) { - table+=8; - } - else { - for(bit=0x01; bit<0x100; bit<<=1) { - if(xor&bit) { - handle_scancode(*table, !(*new&bit)); - need_tasklet_schedule=1; -#if 0 - printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed"); -#endif - } - table++; - } - } - new++; old++; - } - - if(need_tasklet_schedule) - tasklet_schedule(&keyboard_tasklet); -} - - -static void scan_kbd(unsigned long dummy) -{ - struct scan_keyboard *kbd; - - scan_jiffies++; - - for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) { - if(scan_jiffies&1) { - if(!kbd->scan(kbd->s0)) - check_kbd(kbd->table, - kbd->s0, kbd->s1, kbd->length); - else - memcpy(kbd->s0, kbd->s1, kbd->length); - } - else { - if(!kbd->scan(kbd->s1)) - check_kbd(kbd->table, - kbd->s1, kbd->s0, kbd->length); - else - memcpy(kbd->s1, kbd->s0, kbd->length); - } - - } - - init_timer(&scan_timer); - scan_timer.expires = jiffies + SCANHZ; - scan_timer.data = 0; - scan_timer.function = scan_kbd; - add_timer(&scan_timer); -} - - -int register_scan_keyboard(int (*scan)(unsigned char *buffer), - const unsigned char *table, - int length) -{ - struct scan_keyboard *kbd; - - kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL); - if (kbd == NULL) - goto error_out; - - kbd->scan=scan; - kbd->table=table; - kbd->length=length; - - kbd->s0 = kmalloc(length, GFP_KERNEL); - if (kbd->s0 == NULL) - goto error_free_kbd; - - kbd->s1 = kmalloc(length, GFP_KERNEL); - if (kbd->s1 == NULL) - goto error_free_s0; - - memset(kbd->s0, -1, kbd->length); - memset(kbd->s1, -1, kbd->length); - - kbd->next=keyboards; - keyboards=kbd; - - return 0; - - error_free_s0: - kfree(kbd->s0); - - error_free_kbd: - kfree(kbd); - - error_out: - return -ENOMEM; -} - - -void __init scan_kbd_init(void) -{ - init_timer(&scan_timer); - scan_timer.expires = jiffies + SCANHZ; - scan_timer.data = 0; - scan_timer.function = scan_kbd; - add_timer(&scan_timer); - - printk(KERN_INFO "Generic scan keyboard driver initialized\n"); -} diff --git a/drivers/char/scan_keyb.h b/drivers/char/scan_keyb.h deleted file mode 100644 index b4b6112..0000000 --- a/drivers/char/scan_keyb.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __DRIVER_CHAR_SCAN_KEYB_H -#define __DRIVER_CHAR_SCAN_KEYB_H -/* - * $Id: scan_keyb.h,v 1.1 2000/06/10 21:45:30 yaegashi Exp $ - * Copyright (C) 2000 YAEGASHI Takeshi - * Generic scan keyboard driver - */ - -int register_scan_keyboard(int (*scan)(unsigned char *buffer), - const unsigned char *table, - int length); - -void __init scan_kbd_init(void); - -#endif diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index af50d32..5fd314a 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -111,12 +111,13 @@ u_char initial_console_speed; /* This is the per-port data structure */ struct cyclades_port cy_port[] = { - /* CARD# */ - {-1 }, /* ttyS0 */ - {-1 }, /* ttyS1 */ - {-1 }, /* ttyS2 */ - {-1 }, /* ttyS3 */ + /* CARD# */ + {-1}, /* ttyS0 */ + {-1}, /* ttyS1 */ + {-1}, /* ttyS2 */ + {-1}, /* ttyS3 */ }; + #define NR_PORTS ARRAY_SIZE(cy_port) /* @@ -128,42 +129,46 @@ struct cyclades_port cy_port[] = { * HI VHI */ static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, - 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000, - 0}; + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, + 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, + 0 +}; #if 0 -static char baud_co[] = { /* 25 MHz clock option table */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static char baud_co[] = { /* 25 MHz clock option table */ + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; -static char baud_bpr[] = { /* 25 MHz baud rate period table */ - 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, - 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; +static char baud_bpr[] = { /* 25 MHz baud rate period table */ + 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, + 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15 +}; #endif /* I think 166 brd clocks 2401 at 20MHz.... */ /* These values are written directly to tcor, and >> 5 for writing to rcor */ -static u_char baud_co[] = { /* 20 MHz clock option table */ - 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40, - 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static u_char baud_co[] = { /* 20 MHz clock option table */ + 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40, + 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; /* These values written directly to tbpr/rbpr */ -static u_char baud_bpr[] = { /* 20 MHz baud rate period table */ - 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81, - 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10}; - -static u_char baud_cor4[] = { /* receive threshold */ - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07}; - +static u_char baud_bpr[] = { /* 20 MHz baud rate period table */ + 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81, + 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10 +}; +static u_char baud_cor4[] = { /* receive threshold */ + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07 +}; static void shutdown(struct cyclades_port *); -static int startup (struct cyclades_port *); +static int startup(struct cyclades_port *); static void cy_throttle(struct tty_struct *); static void cy_unthrottle(struct tty_struct *); static void config_setup(struct cyclades_port *); @@ -174,16 +179,16 @@ static void show_status(int); #ifdef CONFIG_REMOTE_DEBUG static void debug_setup(void); -void queueDebugChar (int c); +void queueDebugChar(int c); int getDebugChar(void); #define DEBUG_PORT 1 #define DEBUG_LEN 256 typedef struct { - int in; - int out; - unsigned char buf[DEBUG_LEN]; + int in; + int out; + unsigned char buf[DEBUG_LEN]; } debugq; debugq debugiq; @@ -196,7 +201,7 @@ debugq debugiq; * delay, but this wild guess will do for now. */ -void my_udelay (long us) +void my_udelay(long us) { u_char x; volatile u_char *p = &x; @@ -207,62 +212,73 @@ void my_udelay (long us) x |= *p; } -static inline int -serial_paranoia_check(struct cyclades_port *info, char *name, - const char *routine) +static inline int serial_paranoia_check(struct cyclades_port *info, char *name, + const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null cyclades_port for (%s) in %s\n"; - static const char *badrange = - "Warning: cyclades_port out of range for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - - if( (long)info < (long)(&cy_port[0]) - || (long)(&cy_port[NR_PORTS]) < (long)info ){ - printk(badrange, name, routine); - return 1; - } - - if (info->magic != CYCLADES_MAGIC) { - printk(badmagic, name, routine); - return 1; - } + if (!info) { + printk("Warning: null cyclades_port for (%s) in %s\n", name, + routine); + return 1; + } + + if ((long)info < (long)(&cy_port[0]) + || (long)(&cy_port[NR_PORTS]) < (long)info) { + printk("Warning: cyclades_port out of range for (%s) in %s\n", + name, routine); + return 1; + } + + if (info->magic != CYCLADES_MAGIC) { + printk("Warning: bad magic number for serial struct (%s) in " + "%s\n", name, routine); + return 1; + } #endif return 0; -} /* serial_paranoia_check */ +} /* serial_paranoia_check */ #if 0 /* The following diagnostic routines allow the driver to spew information on the screen, even (especially!) during interrupts. */ -void -SP(char *data){ - unsigned long flags; - local_irq_save(flags); - console_print(data); - local_irq_restore(flags); +void SP(char *data) +{ + unsigned long flags; + local_irq_save(flags); + console_print(data); + local_irq_restore(flags); } + char scrn[2]; -void -CP(char data){ - unsigned long flags; - local_irq_save(flags); - scrn[0] = data; - console_print(scrn); - local_irq_restore(flags); -}/* CP */ +void CP(char data) +{ + unsigned long flags; + local_irq_save(flags); + scrn[0] = data; + console_print(scrn); + local_irq_restore(flags); +} /* CP */ -void CP1(int data) { (data<10)? CP(data+'0'): CP(data+'A'-10); }/* CP1 */ -void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }/* CP2 */ -void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */ -void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */ +void CP1(int data) +{ + (data < 10) ? CP(data + '0') : CP(data + 'A' - 10); +} /* CP1 */ +void CP2(int data) +{ + CP1((data >> 4) & 0x0f); + CP1(data & 0x0f); +} /* CP2 */ +void CP4(int data) +{ + CP2((data >> 8) & 0xff); + CP2(data & 0xff); +} /* CP4 */ +void CP8(long data) +{ + CP4((data >> 16) & 0xffff); + CP4(data & 0xffff); +} /* CP8 */ #endif /* This routine waits up to 1000 micro-seconds for the previous @@ -270,87 +286,78 @@ void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */ new command. An error is returned if the previous command didn't finish within the time limit. */ -u_short -write_cy_cmd(volatile u_char *base_addr, u_char cmd) +u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd) { - unsigned long flags; - volatile int i; + unsigned long flags; + volatile int i; - local_irq_save(flags); + local_irq_save(flags); /* Check to see that the previous command has completed */ - for(i = 0 ; i < 100 ; i++){ - if (base_addr[CyCCR] == 0){ - break; - } - my_udelay(10L); + for (i = 0; i < 100; i++) { + if (base_addr[CyCCR] == 0) { + break; + } + my_udelay(10L); } /* if the CCR never cleared, the previous command - didn't finish within the "reasonable time" */ - if ( i == 10 ) { - local_irq_restore(flags); - return (-1); + didn't finish within the "reasonable time" */ + if (i == 10) { + local_irq_restore(flags); + return (-1); } /* Issue the new command */ base_addr[CyCCR] = cmd; - local_irq_restore(flags); - return(0); -} /* write_cy_cmd */ - + local_irq_restore(flags); + return (0); +} /* write_cy_cmd */ /* cy_start and cy_stop provide software output flow control as a function of XON/XOFF, software CTS, and other such stuff. */ -static void -cy_stop(struct tty_struct *tty) +static void cy_stop(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; + unsigned long flags; #ifdef SERIAL_DEBUG_OTHER - printk("cy_stop %s\n", tty->name); /* */ + printk("cy_stop %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_stop")) - return; - - channel = info->line; + if (serial_paranoia_check(info, tty->name, "cy_stop")) + return; - local_irq_save(flags); - base_addr[CyCAR] = (u_char)(channel); /* index channel */ - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); - local_irq_restore(flags); + channel = info->line; - return; -} /* cy_stop */ + local_irq_save(flags); + base_addr[CyCAR] = (u_char) (channel); /* index channel */ + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + local_irq_restore(flags); +} /* cy_stop */ -static void -cy_start(struct tty_struct *tty) +static void cy_start(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; + unsigned long flags; #ifdef SERIAL_DEBUG_OTHER - printk("cy_start %s\n", tty->name); /* */ + printk("cy_start %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_start")) - return; - - channel = info->line; + if (serial_paranoia_check(info, tty->name, "cy_start")) + return; - local_irq_save(flags); - base_addr[CyCAR] = (u_char)(channel); - base_addr[CyIER] |= CyTxMpty; - local_irq_restore(flags); - - return; -} /* cy_start */ + channel = info->line; + local_irq_save(flags); + base_addr[CyCAR] = (u_char) (channel); + base_addr[CyIER] |= CyTxMpty; + local_irq_restore(flags); +} /* cy_start */ /* * This routine is used by the interrupt handler to schedule @@ -358,332 +365,332 @@ cy_start(struct tty_struct *tty) * (also known as the "bottom half"). This can be called any * number of times for any channel without harm. */ -static inline void -cy_sched_event(struct cyclades_port *info, int event) +static inline void cy_sched_event(struct cyclades_port *info, int event) { - info->event |= 1 << event; /* remember what kind of event and who */ - schedule_work(&info->tqueue); -} /* cy_sched_event */ - + info->event |= 1 << event; /* remember what kind of event and who */ + schedule_work(&info->tqueue); +} /* cy_sched_event */ /* The real interrupt service routines are called whenever the card wants its hand held--chars received, out buffer empty, modem change, etc. */ -static irqreturn_t -cd2401_rxerr_interrupt(int irq, void *dev_id) +static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id) { - struct tty_struct *tty; - struct cyclades_port *info; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - unsigned char err, rfoc; - int channel; - char data; - - /* determine the channel and change to that context */ - channel = (u_short ) (base_addr[CyLICR] >> 2); - info = &cy_port[channel]; - info->last_active = jiffies; - - if ((err = base_addr[CyRISR]) & CyTIMEOUT) { - /* This is a receive timeout interrupt, ignore it */ - base_addr[CyREOIR] = CyNOTRANS; - return IRQ_HANDLED; - } - - /* Read a byte of data if there is any - assume the error - * is associated with this character */ + struct tty_struct *tty; + struct cyclades_port *info; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + unsigned char err, rfoc; + int channel; + char data; + + /* determine the channel and change to that context */ + channel = (u_short) (base_addr[CyLICR] >> 2); + info = &cy_port[channel]; + info->last_active = jiffies; + + if ((err = base_addr[CyRISR]) & CyTIMEOUT) { + /* This is a receive timeout interrupt, ignore it */ + base_addr[CyREOIR] = CyNOTRANS; + return IRQ_HANDLED; + } - if ((rfoc = base_addr[CyRFOC]) != 0) - data = base_addr[CyRDR]; - else - data = 0; + /* Read a byte of data if there is any - assume the error + * is associated with this character */ - /* if there is nowhere to put the data, discard it */ - if(info->tty == 0) { + if ((rfoc = base_addr[CyRFOC]) != 0) + data = base_addr[CyRDR]; + else + data = 0; + + /* if there is nowhere to put the data, discard it */ + if (info->tty == 0) { + base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; + return IRQ_HANDLED; + } else { /* there is an open port for this data */ + tty = info->tty; + if (err & info->ignore_status_mask) { + base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; + return IRQ_HANDLED; + } + if (tty_buffer_request_room(tty, 1) != 0) { + if (err & info->read_status_mask) { + if (err & CyBREAK) { + tty_insert_flip_char(tty, data, + TTY_BREAK); + if (info->flags & ASYNC_SAK) { + do_SAK(tty); + } + } else if (err & CyFRAME) { + tty_insert_flip_char(tty, data, + TTY_FRAME); + } else if (err & CyPARITY) { + tty_insert_flip_char(tty, data, + TTY_PARITY); + } else if (err & CyOVERRUN) { + tty_insert_flip_char(tty, 0, + TTY_OVERRUN); + /* + If the flip buffer itself is + overflowing, we still loose + the next incoming character. + */ + if (tty_buffer_request_room(tty, 1) != + 0) { + tty_insert_flip_char(tty, data, + TTY_FRAME); + } + /* These two conditions may imply */ + /* a normal read should be done. */ + /* else if(data & CyTIMEOUT) */ + /* else if(data & CySPECHAR) */ + } else { + tty_insert_flip_char(tty, 0, + TTY_NORMAL); + } + } else { + tty_insert_flip_char(tty, data, TTY_NORMAL); + } + } else { + /* there was a software buffer overrun + and nothing could be done about it!!! */ + } + } + tty_schedule_flip(tty); + /* end of service */ base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; return IRQ_HANDLED; - } - else { /* there is an open port for this data */ - tty = info->tty; - if(err & info->ignore_status_mask){ - base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; - return IRQ_HANDLED; - } - if (tty_buffer_request_room(tty, 1) != 0){ - if (err & info->read_status_mask){ - if(err & CyBREAK){ - tty_insert_flip_char(tty, data, TTY_BREAK); - if (info->flags & ASYNC_SAK){ - do_SAK(tty); - } - }else if(err & CyFRAME){ - tty_insert_flip_char(tty, data, TTY_FRAME); - }else if(err & CyPARITY){ - tty_insert_flip_char(tty, data, TTY_PARITY); - }else if(err & CyOVERRUN){ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - /* - If the flip buffer itself is - overflowing, we still loose - the next incoming character. - */ - if (tty_buffer_request_room(tty, 1) != 0){ - tty_insert_flip_char(tty, data, TTY_FRAME); - } - /* These two conditions may imply */ - /* a normal read should be done. */ - /* else if(data & CyTIMEOUT) */ - /* else if(data & CySPECHAR) */ - }else{ - tty_insert_flip_char(tty, 0, TTY_NORMAL); - } - }else{ - tty_insert_flip_char(tty, data, TTY_NORMAL); - } - }else{ - /* there was a software buffer overrun - and nothing could be done about it!!! */ - } - } - tty_schedule_flip(tty); - /* end of service */ - base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; - return IRQ_HANDLED; -} /* cy_rxerr_interrupt */ - -static irqreturn_t -cd2401_modem_interrupt(int irq, void *dev_id) +} /* cy_rxerr_interrupt */ + +static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) { - struct cyclades_port *info; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; - int mdm_change; - int mdm_status; - - - /* determine the channel and change to that context */ - channel = (u_short ) (base_addr[CyLICR] >> 2); - info = &cy_port[channel]; - info->last_active = jiffies; - - mdm_change = base_addr[CyMISR]; - mdm_status = base_addr[CyMSVR1]; - - if(info->tty == 0){ /* nowhere to put the data, ignore it */ - ; - }else{ - if((mdm_change & CyDCD) - && (info->flags & ASYNC_CHECK_CD)){ - if(mdm_status & CyDCD){ + struct cyclades_port *info; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; + int mdm_change; + int mdm_status; + + /* determine the channel and change to that context */ + channel = (u_short) (base_addr[CyLICR] >> 2); + info = &cy_port[channel]; + info->last_active = jiffies; + + mdm_change = base_addr[CyMISR]; + mdm_status = base_addr[CyMSVR1]; + + if (info->tty == 0) { /* nowhere to put the data, ignore it */ + ; + } else { + if ((mdm_change & CyDCD) + && (info->flags & ASYNC_CHECK_CD)) { + if (mdm_status & CyDCD) { /* CP('!'); */ - cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); - } else { + cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); + } else { /* CP('@'); */ - cy_sched_event(info, Cy_EVENT_HANGUP); - } - } - if((mdm_change & CyCTS) - && (info->flags & ASYNC_CTS_FLOW)){ - if(info->tty->stopped){ - if(mdm_status & CyCTS){ - /* !!! cy_start isn't used because... */ - info->tty->stopped = 0; - base_addr[CyIER] |= CyTxMpty; - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + cy_sched_event(info, Cy_EVENT_HANGUP); + } } - }else{ - if(!(mdm_status & CyCTS)){ - /* !!! cy_stop isn't used because... */ - info->tty->stopped = 1; - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); + if ((mdm_change & CyCTS) + && (info->flags & ASYNC_CTS_FLOW)) { + if (info->tty->stopped) { + if (mdm_status & CyCTS) { + /* !!! cy_start isn't used because... */ + info->tty->stopped = 0; + base_addr[CyIER] |= CyTxMpty; + cy_sched_event(info, + Cy_EVENT_WRITE_WAKEUP); + } + } else { + if (!(mdm_status & CyCTS)) { + /* !!! cy_stop isn't used because... */ + info->tty->stopped = 1; + base_addr[CyIER] &= + ~(CyTxMpty | CyTxRdy); + } + } + } + if (mdm_status & CyDSR) { } - } - } - if(mdm_status & CyDSR){ } - } - base_addr[CyMEOIR] = 0; - return IRQ_HANDLED; -} /* cy_modem_interrupt */ + base_addr[CyMEOIR] = 0; + return IRQ_HANDLED; +} /* cy_modem_interrupt */ -static irqreturn_t -cd2401_tx_interrupt(int irq, void *dev_id) +static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) { - struct cyclades_port *info; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; - int char_count, saved_cnt; - int outch; + struct cyclades_port *info; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; + int char_count, saved_cnt; + int outch; - /* determine the channel and change to that context */ - channel = (u_short ) (base_addr[CyLICR] >> 2); + /* determine the channel and change to that context */ + channel = (u_short) (base_addr[CyLICR] >> 2); #ifdef CONFIG_REMOTE_DEBUG - if (channel == DEBUG_PORT) { - panic ("TxInt on debug port!!!"); - } + if (channel == DEBUG_PORT) { + panic("TxInt on debug port!!!"); + } #endif - info = &cy_port[channel]; + info = &cy_port[channel]; - /* validate the port number (as configured and open) */ - if( (channel < 0) || (NR_PORTS <= channel) ){ - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); - base_addr[CyTEOIR] = CyNOTRANS; - return IRQ_HANDLED; - } - info->last_active = jiffies; - if(info->tty == 0){ - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); - if (info->xmit_cnt < WAKEUP_CHARS) { - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); - } - base_addr[CyTEOIR] = CyNOTRANS; - return IRQ_HANDLED; - } - - /* load the on-chip space available for outbound data */ - saved_cnt = char_count = base_addr[CyTFTC]; - - if(info->x_char) { /* send special char */ - outch = info->x_char; - base_addr[CyTDR] = outch; - char_count--; - info->x_char = 0; - } - - if (info->x_break){ - /* The Cirrus chip requires the "Embedded Transmit - Commands" of start break, delay, and end break - sequences to be sent. The duration of the - break is given in TICs, which runs at HZ - (typically 100) and the PPR runs at 200 Hz, - so the delay is duration * 200/HZ, and thus a - break can run from 1/100 sec to about 5/4 sec. - Need to check these values - RGH 141095. - */ - base_addr[CyTDR] = 0; /* start break */ - base_addr[CyTDR] = 0x81; - base_addr[CyTDR] = 0; /* delay a bit */ - base_addr[CyTDR] = 0x82; - base_addr[CyTDR] = info->x_break*200/HZ; - base_addr[CyTDR] = 0; /* terminate break */ - base_addr[CyTDR] = 0x83; - char_count -= 7; - info->x_break = 0; - } - - while (char_count > 0){ - if (!info->xmit_cnt){ - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); - break; - } - if (info->xmit_buf == 0){ - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); - break; - } - if (info->tty->stopped || info->tty->hw_stopped){ - base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); - break; - } - /* Because the Embedded Transmit Commands have been - enabled, we must check to see if the escape - character, NULL, is being sent. If it is, we - must ensure that there is room for it to be - doubled in the output stream. Therefore we - no longer advance the pointer when the character - is fetched, but rather wait until after the check - for a NULL output character. (This is necessary - because there may not be room for the two chars - needed to send a NULL. - */ - outch = info->xmit_buf[info->xmit_tail]; - if( outch ){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (PAGE_SIZE - 1); - base_addr[CyTDR] = outch; - char_count--; - }else{ - if(char_count > 1){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (PAGE_SIZE - 1); + /* validate the port number (as configured and open) */ + if ((channel < 0) || (NR_PORTS <= channel)) { + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + base_addr[CyTEOIR] = CyNOTRANS; + return IRQ_HANDLED; + } + info->last_active = jiffies; + if (info->tty == 0) { + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } + base_addr[CyTEOIR] = CyNOTRANS; + return IRQ_HANDLED; + } + + /* load the on-chip space available for outbound data */ + saved_cnt = char_count = base_addr[CyTFTC]; + + if (info->x_char) { /* send special char */ + outch = info->x_char; base_addr[CyTDR] = outch; - base_addr[CyTDR] = 0; char_count--; - char_count--; - }else{ - break; - } + info->x_char = 0; } - } - if (info->xmit_cnt < WAKEUP_CHARS) { - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); - } - base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; - return IRQ_HANDLED; -} /* cy_tx_interrupt */ + if (info->x_break) { + /* The Cirrus chip requires the "Embedded Transmit + Commands" of start break, delay, and end break + sequences to be sent. The duration of the + break is given in TICs, which runs at HZ + (typically 100) and the PPR runs at 200 Hz, + so the delay is duration * 200/HZ, and thus a + break can run from 1/100 sec to about 5/4 sec. + Need to check these values - RGH 141095. + */ + base_addr[CyTDR] = 0; /* start break */ + base_addr[CyTDR] = 0x81; + base_addr[CyTDR] = 0; /* delay a bit */ + base_addr[CyTDR] = 0x82; + base_addr[CyTDR] = info->x_break * 200 / HZ; + base_addr[CyTDR] = 0; /* terminate break */ + base_addr[CyTDR] = 0x83; + char_count -= 7; + info->x_break = 0; + } + + while (char_count > 0) { + if (!info->xmit_cnt) { + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + break; + } + if (info->xmit_buf == 0) { + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + break; + } + if (info->tty->stopped || info->tty->hw_stopped) { + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + break; + } + /* Because the Embedded Transmit Commands have been + enabled, we must check to see if the escape + character, NULL, is being sent. If it is, we + must ensure that there is room for it to be + doubled in the output stream. Therefore we + no longer advance the pointer when the character + is fetched, but rather wait until after the check + for a NULL output character. (This is necessary + because there may not be room for the two chars + needed to send a NULL. + */ + outch = info->xmit_buf[info->xmit_tail]; + if (outch) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) + & (PAGE_SIZE - 1); + base_addr[CyTDR] = outch; + char_count--; + } else { + if (char_count > 1) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) + & (PAGE_SIZE - 1); + base_addr[CyTDR] = outch; + base_addr[CyTDR] = 0; + char_count--; + char_count--; + } else { + break; + } + } + } + + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } + base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; + return IRQ_HANDLED; +} /* cy_tx_interrupt */ -static irqreturn_t -cd2401_rx_interrupt(int irq, void *dev_id) +static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) { - struct tty_struct *tty; - struct cyclades_port *info; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; - char data; - int char_count; - int save_cnt; - int len; - - /* determine the channel and change to that context */ - channel = (u_short ) (base_addr[CyLICR] >> 2); - info = &cy_port[channel]; - info->last_active = jiffies; - save_cnt = char_count = base_addr[CyRFOC]; + struct tty_struct *tty; + struct cyclades_port *info; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; + char data; + int char_count; + int save_cnt; + int len; + + /* determine the channel and change to that context */ + channel = (u_short) (base_addr[CyLICR] >> 2); + info = &cy_port[channel]; + info->last_active = jiffies; + save_cnt = char_count = base_addr[CyRFOC]; #ifdef CONFIG_REMOTE_DEBUG - if (channel == DEBUG_PORT) { - while (char_count--) { - data = base_addr[CyRDR]; - queueDebugChar(data); - } - } - else + if (channel == DEBUG_PORT) { + while (char_count--) { + data = base_addr[CyRDR]; + queueDebugChar(data); + } + } else #endif - /* if there is nowhere to put the data, discard it */ - if(info->tty == 0){ - while(char_count--){ - data = base_addr[CyRDR]; - } - }else{ /* there is an open port for this data */ - tty = info->tty; - /* load # characters available from the chip */ + /* if there is nowhere to put the data, discard it */ + if (info->tty == 0) { + while (char_count--) { + data = base_addr[CyRDR]; + } + } else { /* there is an open port for this data */ + tty = info->tty; + /* load # characters available from the chip */ #ifdef CYCLOM_ENABLE_MONITORING - ++info->mon.int_count; - info->mon.char_count += char_count; - if (char_count > info->mon.char_max) - info->mon.char_max = char_count; - info->mon.char_last = char_count; -#endif - len = tty_buffer_request_room(tty, char_count); - while(len--){ - data = base_addr[CyRDR]; - tty_insert_flip_char(tty, data, TTY_NORMAL); + ++info->mon.int_count; + info->mon.char_count += char_count; + if (char_count > info->mon.char_max) + info->mon.char_max = char_count; + info->mon.char_last = char_count; +#endif + len = tty_buffer_request_room(tty, char_count); + while (len--) { + data = base_addr[CyRDR]; + tty_insert_flip_char(tty, data, TTY_NORMAL); #ifdef CYCLOM_16Y_HACK - udelay(10L); + udelay(10L); #endif - } - tty_schedule_flip(tty); - } - /* end of service */ - base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; - return IRQ_HANDLED; -} /* cy_rx_interrupt */ + } + tty_schedule_flip(tty); + } + /* end of service */ + base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; + return IRQ_HANDLED; +} /* cy_rx_interrupt */ /* * This routine is used to handle the "bottom half" processing for the @@ -705,192 +712,188 @@ cd2401_rx_interrupt(int irq, void *dev_id) * structure) to the bottom half of the driver. Previous kernels * had to poll every port to see if that port needed servicing. */ -static void -do_softint(struct work_struct *ugly_api) +static void do_softint(struct work_struct *ugly_api) { - struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue); - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; + struct cyclades_port *info = + container_of(ugly_api, struct cyclades_port, tqueue); + struct tty_struct *tty; - if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { - tty_hangup(info->tty); - wake_up_interruptible(&info->open_wait); - info->flags &= ~ASYNC_NORMAL_ACTIVE; - } - if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { - wake_up_interruptible(&info->open_wait); - } - if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { - tty_wakeup(tty); - } -} /* do_softint */ + tty = info->tty; + if (!tty) + return; + if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { + tty_hangup(info->tty); + wake_up_interruptible(&info->open_wait); + info->flags &= ~ASYNC_NORMAL_ACTIVE; + } + if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { + wake_up_interruptible(&info->open_wait); + } + if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { + tty_wakeup(tty); + } +} /* do_softint */ /* This is called whenever a port becomes active; interrupts are enabled and DTR & RTS are turned on. */ -static int -startup(struct cyclades_port * info) +static int startup(struct cyclades_port *info) { - unsigned long flags; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; + unsigned long flags; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; - if (info->flags & ASYNC_INITIALIZED){ - return 0; - } + if (info->flags & ASYNC_INITIALIZED) { + return 0; + } - if (!info->type){ - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (!info->type) { + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + return 0; } - return 0; - } - if (!info->xmit_buf){ - info->xmit_buf = (unsigned char *) get_zeroed_page (GFP_KERNEL); - if (!info->xmit_buf){ - return -ENOMEM; + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); + if (!info->xmit_buf) { + return -ENOMEM; + } } - } - config_setup(info); + config_setup(info); - channel = info->line; + channel = info->line; #ifdef SERIAL_DEBUG_OPEN - printk("startup channel %d\n", channel); + printk("startup channel %d\n", channel); #endif - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; - write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR); + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR); - base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */ + base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */ base_addr[CyMSVR1] = CyRTS; /* CP('S');CP('1'); */ base_addr[CyMSVR2] = CyDTR; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); + printk("cyc: %d: raising DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); #endif base_addr[CyIER] |= CyRxData; info->flags |= ASYNC_INITIALIZED; - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); } info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - local_irq_restore(flags); + local_irq_restore(flags); #ifdef SERIAL_DEBUG_OPEN - printk(" done\n"); + printk(" done\n"); #endif - return 0; -} /* startup */ + return 0; +} /* startup */ -void -start_xmit( struct cyclades_port *info ) +void start_xmit(struct cyclades_port *info) { - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; - channel = info->line; - local_irq_save(flags); + channel = info->line; + local_irq_save(flags); base_addr[CyCAR] = channel; base_addr[CyIER] |= CyTxMpty; - local_irq_restore(flags); -} /* start_xmit */ + local_irq_restore(flags); +} /* start_xmit */ /* * This routine shuts down a serial port; interrupts are disabled, * and DTR is dropped if the hangup on close termio flag is on. */ -static void -shutdown(struct cyclades_port * info) +static void shutdown(struct cyclades_port *info) { - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; - if (!(info->flags & ASYNC_INITIALIZED)){ + if (!(info->flags & ASYNC_INITIALIZED)) { /* CP('$'); */ - return; - } + return; + } - channel = info->line; + channel = info->line; #ifdef SERIAL_DEBUG_OPEN - printk("shutdown channel %d\n", channel); + printk("shutdown channel %d\n", channel); #endif - /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE - SENT BEFORE DROPPING THE LINE !!! (Perhaps - set some flag that is read when XMTY happens.) - Other choices are to delay some fixed interval - or schedule some later processing. - */ - local_irq_save(flags); - if (info->xmit_buf){ - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = NULL; + /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE + SENT BEFORE DROPPING THE LINE !!! (Perhaps + set some flag that is read when XMTY happens.) + Other choices are to delay some fixed interval + or schedule some later processing. + */ + local_irq_save(flags); + if (info->xmit_buf) { + free_page((unsigned long)info->xmit_buf); + info->xmit_buf = NULL; } - base_addr[CyCAR] = (u_char)channel; + base_addr[CyCAR] = (u_char) channel; if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - base_addr[CyMSVR1] = 0; + base_addr[CyMSVR1] = 0; /* CP('C');CP('1'); */ - base_addr[CyMSVR2] = 0; + base_addr[CyMSVR2] = 0; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: dropping DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); + printk("cyc: %d: dropping DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); #endif - } - write_cy_cmd(base_addr,CyDIS_RCVR); - /* it may be appropriate to clear _XMIT at - some later date (after testing)!!! */ + } + write_cy_cmd(base_addr, CyDIS_RCVR); + /* it may be appropriate to clear _XMIT at + some later date (after testing)!!! */ - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); } info->flags &= ~ASYNC_INITIALIZED; - local_irq_restore(flags); + local_irq_restore(flags); #ifdef SERIAL_DEBUG_OPEN - printk(" done\n"); + printk(" done\n"); #endif - return; -} /* shutdown */ +} /* shutdown */ /* * This routine finds or computes the various line characteristics. */ -static void -config_setup(struct cyclades_port * info) +static void config_setup(struct cyclades_port *info) { - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; - unsigned cflag; - int i; - unsigned char ti, need_init_chan = 0; - - if (!info->tty || !info->tty->termios){ - return; - } - if (info->line == -1){ - return; - } - cflag = info->tty->termios->c_cflag; - - /* baud rate */ - i = cflag & CBAUD; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + unsigned cflag; + int i; + unsigned char ti, need_init_chan = 0; + + if (!info->tty || !info->tty->termios) { + return; + } + if (info->line == -1) { + return; + } + cflag = info->tty->termios->c_cflag; + + /* baud rate */ + i = cflag & CBAUD; #ifdef CBAUDEX /* Starting with kernel 1.1.65, there is direct support for higher baud rates. The following code supports those @@ -900,120 +903,123 @@ config_setup(struct cyclades_port * info) is still the possibility of supporting 75 kbit/sec with the Cyclades board.) */ - if (i & CBAUDEX) { - if (i == B57600) - i = 16; - else if(i == B115200) - i = 18; + if (i & CBAUDEX) { + if (i == B57600) + i = 16; + else if (i == B115200) + i = 18; #ifdef B78600 - else if(i == B78600) - i = 17; + else if (i == B78600) + i = 17; #endif - else - info->tty->termios->c_cflag &= ~CBAUDEX; - } -#endif - if (i == 15) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - i += 1; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - i += 3; - } - /* Don't ever change the speed of the console port. It will - * run at the speed specified in bootinfo, or at 19.2K */ - /* Actually, it should run at whatever speed 166Bug was using */ - /* Note info->timeout isn't used at present */ - if (info != serial_console_info) { - info->tbpr = baud_bpr[i]; /* Tx BPR */ - info->tco = baud_co[i]; /* Tx CO */ - info->rbpr = baud_bpr[i]; /* Rx BPR */ - info->rco = baud_co[i] >> 5; /* Rx CO */ - if (baud_table[i] == 134) { - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; - /* get it right for 134.5 baud */ - } else if (baud_table[i]) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; - /* this needs to be propagated into the card info */ + else + info->tty->termios->c_cflag &= ~CBAUDEX; + } +#endif + if (i == 15) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + i += 1; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + i += 3; + } + /* Don't ever change the speed of the console port. It will + * run at the speed specified in bootinfo, or at 19.2K */ + /* Actually, it should run at whatever speed 166Bug was using */ + /* Note info->timeout isn't used at present */ + if (info != serial_console_info) { + info->tbpr = baud_bpr[i]; /* Tx BPR */ + info->tco = baud_co[i]; /* Tx CO */ + info->rbpr = baud_bpr[i]; /* Rx BPR */ + info->rco = baud_co[i] >> 5; /* Rx CO */ + if (baud_table[i] == 134) { + info->timeout = + (info->xmit_fifo_size * HZ * 30 / 269) + 2; + /* get it right for 134.5 baud */ + } else if (baud_table[i]) { + info->timeout = + (info->xmit_fifo_size * HZ * 15 / baud_table[i]) + + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } + } + /* By tradition (is it a standard?) a baud rate of zero + implies the line should be/has been closed. A bit + later in this routine such a test is performed. */ + + /* byte size and parity */ + info->cor7 = 0; + info->cor6 = 0; + info->cor5 = 0; + info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]); /* receive threshold */ + /* Following two lines added 101295, RGH. */ + /* It is obviously wrong to access CyCORx, and not info->corx here, + * try and remember to fix it later! */ + channel = info->line; + base_addr[CyCAR] = (u_char) channel; + if (C_CLOCAL(info->tty)) { + if (base_addr[CyIER] & CyMdmCh) + base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */ + /* ignore 1->0 modem transitions */ + if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) + base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD); + /* ignore 0->1 modem transitions */ + if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) + base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD); } else { - info->timeout = 0; - } - } - /* By tradition (is it a standard?) a baud rate of zero - implies the line should be/has been closed. A bit - later in this routine such a test is performed. */ - - /* byte size and parity */ - info->cor7 = 0; - info->cor6 = 0; - info->cor5 = 0; - info->cor4 = (info->default_threshold - ? info->default_threshold - : baud_cor4[i]); /* receive threshold */ - /* Following two lines added 101295, RGH. */ - /* It is obviously wrong to access CyCORx, and not info->corx here, - * try and remember to fix it later! */ - channel = info->line; - base_addr[CyCAR] = (u_char)channel; - if (C_CLOCAL(info->tty)) { - if (base_addr[CyIER] & CyMdmCh) - base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */ - /* ignore 1->0 modem transitions */ - if (base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) - base_addr[CyCOR4] &= ~(CyDSR|CyCTS|CyDCD); - /* ignore 0->1 modem transitions */ - if (base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) - base_addr[CyCOR5] &= ~(CyDSR|CyCTS|CyDCD); - } else { - if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh) - base_addr[CyIER] |= CyMdmCh; /* with modem intr */ - /* act on 1->0 modem transitions */ - if ((base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD)) - base_addr[CyCOR4] |= CyDSR|CyCTS|CyDCD; - /* act on 0->1 modem transitions */ - if ((base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD)) - base_addr[CyCOR5] |= CyDSR|CyCTS|CyDCD; - } - info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP; - info->cor2 = CyETC; - switch(cflag & CSIZE){ - case CS5: - info->cor1 = Cy_5_BITS; - break; - case CS6: - info->cor1 = Cy_6_BITS; - break; - case CS7: - info->cor1 = Cy_7_BITS; - break; - case CS8: - info->cor1 = Cy_8_BITS; - break; - } - if (cflag & PARENB){ - if (cflag & PARODD){ - info->cor1 |= CyPARITY_O; - }else{ - info->cor1 |= CyPARITY_E; - } - }else{ - info->cor1 |= CyPARITY_NONE; - } - - /* CTS flow control flag */ + if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh) + base_addr[CyIER] |= CyMdmCh; /* with modem intr */ + /* act on 1->0 modem transitions */ + if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) != + (CyDSR | CyCTS | CyDCD)) + base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD; + /* act on 0->1 modem transitions */ + if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) != + (CyDSR | CyCTS | CyDCD)) + base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD; + } + info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP; + info->cor2 = CyETC; + switch (cflag & CSIZE) { + case CS5: + info->cor1 = Cy_5_BITS; + break; + case CS6: + info->cor1 = Cy_6_BITS; + break; + case CS7: + info->cor1 = Cy_7_BITS; + break; + case CS8: + info->cor1 = Cy_8_BITS; + break; + } + if (cflag & PARENB) { + if (cflag & PARODD) { + info->cor1 |= CyPARITY_O; + } else { + info->cor1 |= CyPARITY_E; + } + } else { + info->cor1 |= CyPARITY_NONE; + } + + /* CTS flow control flag */ #if 0 - /* Don't complcate matters for now! RGH 141095 */ - if (cflag & CRTSCTS){ - info->flags |= ASYNC_CTS_FLOW; - info->cor2 |= CyCtsAE; - }else{ - info->flags &= ~ASYNC_CTS_FLOW; - info->cor2 &= ~CyCtsAE; - } -#endif - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; + /* Don't complcate matters for now! RGH 141095 */ + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->cor2 |= CyCtsAE; + } else { + info->flags &= ~ASYNC_CTS_FLOW; + info->cor2 &= ~CyCtsAE; + } +#endif + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else + info->flags |= ASYNC_CHECK_CD; /*********************************************** The hardware option, CyRtsAO, presents RTS when @@ -1025,149 +1031,146 @@ config_setup(struct cyclades_port * info) cable. Contact Marcio Saito for details. ***********************************************/ - channel = info->line; + channel = info->line; - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; /* CyCMR set once only in mvme167_init_serial() */ if (base_addr[CyLICR] != channel << 2) - base_addr[CyLICR] = channel << 2; + base_addr[CyLICR] = channel << 2; if (base_addr[CyLIVR] != 0x5c) - base_addr[CyLIVR] = 0x5c; + base_addr[CyLIVR] = 0x5c; - /* tx and rx baud rate */ + /* tx and rx baud rate */ if (base_addr[CyCOR1] != info->cor1) - need_init_chan = 1; + need_init_chan = 1; if (base_addr[CyTCOR] != info->tco) - base_addr[CyTCOR] = info->tco; + base_addr[CyTCOR] = info->tco; if (base_addr[CyTBPR] != info->tbpr) - base_addr[CyTBPR] = info->tbpr; + base_addr[CyTBPR] = info->tbpr; if (base_addr[CyRCOR] != info->rco) - base_addr[CyRCOR] = info->rco; + base_addr[CyRCOR] = info->rco; if (base_addr[CyRBPR] != info->rbpr) - base_addr[CyRBPR] = info->rbpr; + base_addr[CyRBPR] = info->rbpr; /* set line characteristics according configuration */ if (base_addr[CySCHR1] != START_CHAR(info->tty)) - base_addr[CySCHR1] = START_CHAR(info->tty); + base_addr[CySCHR1] = START_CHAR(info->tty); if (base_addr[CySCHR2] != STOP_CHAR(info->tty)) - base_addr[CySCHR2] = STOP_CHAR(info->tty); + base_addr[CySCHR2] = STOP_CHAR(info->tty); if (base_addr[CySCRL] != START_CHAR(info->tty)) - base_addr[CySCRL] = START_CHAR(info->tty); + base_addr[CySCRL] = START_CHAR(info->tty); if (base_addr[CySCRH] != START_CHAR(info->tty)) - base_addr[CySCRH] = START_CHAR(info->tty); + base_addr[CySCRH] = START_CHAR(info->tty); if (base_addr[CyCOR1] != info->cor1) - base_addr[CyCOR1] = info->cor1; + base_addr[CyCOR1] = info->cor1; if (base_addr[CyCOR2] != info->cor2) - base_addr[CyCOR2] = info->cor2; + base_addr[CyCOR2] = info->cor2; if (base_addr[CyCOR3] != info->cor3) - base_addr[CyCOR3] = info->cor3; + base_addr[CyCOR3] = info->cor3; if (base_addr[CyCOR4] != info->cor4) - base_addr[CyCOR4] = info->cor4; + base_addr[CyCOR4] = info->cor4; if (base_addr[CyCOR5] != info->cor5) - base_addr[CyCOR5] = info->cor5; + base_addr[CyCOR5] = info->cor5; if (base_addr[CyCOR6] != info->cor6) - base_addr[CyCOR6] = info->cor6; + base_addr[CyCOR6] = info->cor6; if (base_addr[CyCOR7] != info->cor7) - base_addr[CyCOR7] = info->cor7; + base_addr[CyCOR7] = info->cor7; if (need_init_chan) - write_cy_cmd(base_addr,CyINIT_CHAN); + write_cy_cmd(base_addr, CyINIT_CHAN); - base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */ + base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */ /* 2ms default rx timeout */ ti = info->default_timeout ? info->default_timeout : 0x02; if (base_addr[CyRTPRL] != ti) - base_addr[CyRTPRL] = ti; + base_addr[CyRTPRL] = ti; if (base_addr[CyRTPRH] != 0) - base_addr[CyRTPRH] = 0; + base_addr[CyRTPRH] = 0; /* Set up RTS here also ????? RGH 141095 */ - if(i == 0){ /* baud rate is zero, turn off line */ - if ((base_addr[CyMSVR2] & CyDTR) == CyDTR) - base_addr[CyMSVR2] = 0; + if (i == 0) { /* baud rate is zero, turn off line */ + if ((base_addr[CyMSVR2] & CyDTR) == CyDTR) + base_addr[CyMSVR2] = 0; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: dropping DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); + printk("cyc: %d: dropping DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); #endif - }else{ - if ((base_addr[CyMSVR2] & CyDTR) != CyDTR) - base_addr[CyMSVR2] = CyDTR; + } else { + if ((base_addr[CyMSVR2] & CyDTR) != CyDTR) + base_addr[CyMSVR2] = CyDTR; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); + printk("cyc: %d: raising DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); #endif } - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); } - local_irq_restore(flags); - -} /* config_setup */ + local_irq_restore(flags); +} /* config_setup */ -static void -cy_put_char(struct tty_struct *tty, unsigned char ch) +static void cy_put_char(struct tty_struct *tty, unsigned char ch) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; #ifdef SERIAL_DEBUG_IO - printk("cy_put_char %s(0x%02x)\n", tty->name, ch); + printk("cy_put_char %s(0x%02x)\n", tty->name, ch); #endif - if (serial_paranoia_check(info, tty->name, "cy_put_char")) - return; + if (serial_paranoia_check(info, tty->name, "cy_put_char")) + return; - if (!info->xmit_buf) - return; + if (!info->xmit_buf) + return; - local_irq_save(flags); + local_irq_save(flags); if (info->xmit_cnt >= PAGE_SIZE - 1) { - local_irq_restore(flags); - return; + local_irq_restore(flags); + return; } info->xmit_buf[info->xmit_head++] = ch; info->xmit_head &= PAGE_SIZE - 1; info->xmit_cnt++; - local_irq_restore(flags); -} /* cy_put_char */ - + local_irq_restore(flags); +} /* cy_put_char */ -static void -cy_flush_chars(struct tty_struct *tty) +static void cy_flush_chars(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + #ifdef SERIAL_DEBUG_IO - printk("cy_flush_chars %s\n", tty->name); /* */ + printk("cy_flush_chars %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) - return; + if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) + return; - if (info->xmit_cnt <= 0 || tty->stopped - || tty->hw_stopped || !info->xmit_buf) - return; + if (info->xmit_cnt <= 0 || tty->stopped + || tty->hw_stopped || !info->xmit_buf) + return; - channel = info->line; + channel = info->line; - local_irq_save(flags); + local_irq_save(flags); base_addr[CyCAR] = channel; base_addr[CyIER] |= CyTxMpty; - local_irq_restore(flags); -} /* cy_flush_chars */ - + local_irq_restore(flags); +} /* cy_flush_chars */ /* This routine gets called when tty_write has put something into the write_queue. If the port is not already transmitting stuff, @@ -1175,650 +1178,616 @@ cy_flush_chars(struct tty_struct *tty) routine will then ensure that the characters are sent. If the port is already active, there is no need to kick it. */ -static int -cy_write(struct tty_struct * tty, - const unsigned char *buf, int count) +static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - int c, total = 0; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + int c, total = 0; #ifdef SERIAL_DEBUG_IO - printk("cy_write %s\n", tty->name); /* */ + printk("cy_write %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_write")){ - return 0; - } - - if (!info->xmit_buf){ - return 0; - } - - while (1) { - local_irq_save(flags); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - local_irq_restore(flags); - break; - } - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); - - buf += c; - count -= c; - total += c; - } - - if (info->xmit_cnt - && !tty->stopped - && !tty->hw_stopped ) { - start_xmit(info); - } - return total; -} /* cy_write */ + if (serial_paranoia_check(info, tty->name, "cy_write")) { + return 0; + } + if (!info->xmit_buf) { + return 0; + } -static int -cy_write_room(struct tty_struct *tty) + while (1) { + local_irq_save(flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + local_irq_restore(flags); + break; + } + + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = + (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + local_irq_restore(flags); + + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + start_xmit(info); + } + return total; +} /* cy_write */ + +static int cy_write_room(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int ret; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int ret; + #ifdef SERIAL_DEBUG_IO - printk("cy_write_room %s\n", tty->name); /* */ + printk("cy_write_room %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_write_room")) - return 0; - ret = PAGE_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} /* cy_write_room */ - + if (serial_paranoia_check(info, tty->name, "cy_write_room")) + return 0; + ret = PAGE_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} /* cy_write_room */ -static int -cy_chars_in_buffer(struct tty_struct *tty) +static int cy_chars_in_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + #ifdef SERIAL_DEBUG_IO - printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ + printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) - return 0; - - return info->xmit_cnt; -} /* cy_chars_in_buffer */ + if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} /* cy_chars_in_buffer */ -static void -cy_flush_buffer(struct tty_struct *tty) +static void cy_flush_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + #ifdef SERIAL_DEBUG_IO - printk("cy_flush_buffer %s\n", tty->name); /* */ + printk("cy_flush_buffer %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) - return; - local_irq_save(flags); + if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) + return; + local_irq_save(flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - local_irq_restore(flags); - tty_wakeup(tty); -} /* cy_flush_buffer */ - + local_irq_restore(flags); + tty_wakeup(tty); +} /* cy_flush_buffer */ /* This routine is called by the upper-layer tty layer to signal that incoming characters should be throttled or that the throttle should be released. */ -static void -cy_throttle(struct tty_struct * tty) +static void cy_throttle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; #ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); - printk("cy_throttle %s\n", tty->name); + char buf[64]; + + printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); + printk("cy_throttle %s\n", tty->name); #endif - if (serial_paranoia_check(info, tty->name, "cy_nthrottle")){ - return; - } + if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) { + return; + } - if (I_IXOFF(tty)) { - info->x_char = STOP_CHAR(tty); - /* Should use the "Send Special Character" feature!!! */ - } + if (I_IXOFF(tty)) { + info->x_char = STOP_CHAR(tty); + /* Should use the "Send Special Character" feature!!! */ + } - channel = info->line; + channel = info->line; - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; base_addr[CyMSVR1] = 0; - local_irq_restore(flags); - - return; -} /* cy_throttle */ - + local_irq_restore(flags); +} /* cy_throttle */ -static void -cy_unthrottle(struct tty_struct * tty) +static void cy_unthrottle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; #ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); - printk("cy_unthrottle %s\n", tty->name); + char buf[64]; + + printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); + printk("cy_unthrottle %s\n", tty->name); #endif - if (serial_paranoia_check(info, tty->name, "cy_nthrottle")){ - return; - } + if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) { + return; + } - if (I_IXOFF(tty)) { - info->x_char = START_CHAR(tty); - /* Should use the "Send Special Character" feature!!! */ - } + if (I_IXOFF(tty)) { + info->x_char = START_CHAR(tty); + /* Should use the "Send Special Character" feature!!! */ + } - channel = info->line; + channel = info->line; - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; base_addr[CyMSVR1] = CyRTS; - local_irq_restore(flags); - - return; -} /* cy_unthrottle */ + local_irq_restore(flags); +} /* cy_unthrottle */ static int -get_serial_info(struct cyclades_port * info, - struct serial_struct __user * retinfo) +get_serial_info(struct cyclades_port *info, + struct serial_struct __user * retinfo) { - struct serial_struct tmp; + struct serial_struct tmp; /* CP('g'); */ - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->line; - tmp.irq = 0; - tmp.flags = info->flags; - tmp.baud_base = 0; /*!!!*/ - tmp.close_delay = info->close_delay; - tmp.custom_divisor = 0; /*!!!*/ - tmp.hub6 = 0; /*!!!*/ - return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; -} /* get_serial_info */ + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->line; + tmp.irq = 0; + tmp.flags = info->flags; + tmp.baud_base = 0; /*!!! */ + tmp.close_delay = info->close_delay; + tmp.custom_divisor = 0; /*!!! */ + tmp.hub6 = 0; /*!!! */ + return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; +} /* get_serial_info */ static int -set_serial_info(struct cyclades_port * info, - struct serial_struct __user * new_info) +set_serial_info(struct cyclades_port *info, + struct serial_struct __user * new_info) { - struct serial_struct new_serial; - struct cyclades_port old_info; + struct serial_struct new_serial; + struct cyclades_port old_info; /* CP('s'); */ - if (!new_info) - return -EFAULT; - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - old_info = *info; + if (!new_info) + return -EFAULT; + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + old_info = *info; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != + (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + goto check_and_exit; + } - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.close_delay != info->close_delay) || - ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != - (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) - return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - goto check_and_exit; - } + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + info->flags = ((info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->close_delay = new_serial.close_delay; - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ +check_and_exit: + if (info->flags & ASYNC_INITIALIZED) { + config_setup(info); + return 0; + } + return startup(info); +} /* set_serial_info */ - info->flags = ((info->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->close_delay = new_serial.close_delay; +static int cy_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int channel; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + unsigned long flags; + unsigned char status; + channel = info->line; -check_and_exit: - if (info->flags & ASYNC_INITIALIZED){ - config_setup(info); - return 0; - }else{ - return startup(info); - } -} /* set_serial_info */ + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + status = base_addr[CyMSVR1] | base_addr[CyMSVR2]; + local_irq_restore(flags); -static int -cy_tiocmget(struct tty_struct *tty, struct file *file) -{ - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int channel; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - unsigned long flags; - unsigned char status; - - channel = info->line; - - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; - status = base_addr[CyMSVR1] | base_addr[CyMSVR2]; - local_irq_restore(flags); - - return ((status & CyRTS) ? TIOCM_RTS : 0) - | ((status & CyDTR) ? TIOCM_DTR : 0) - | ((status & CyDCD) ? TIOCM_CAR : 0) - | ((status & CyDSR) ? TIOCM_DSR : 0) - | ((status & CyCTS) ? TIOCM_CTS : 0); -} /* cy_tiocmget */ + return ((status & CyRTS) ? TIOCM_RTS : 0) + | ((status & CyDTR) ? TIOCM_DTR : 0) + | ((status & CyDCD) ? TIOCM_CAR : 0) + | ((status & CyDSR) ? TIOCM_DSR : 0) + | ((status & CyCTS) ? TIOCM_CTS : 0); +} /* cy_tiocmget */ static int cy_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int channel; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - unsigned long flags; - - channel = info->line; - - if (set & TIOCM_RTS){ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int channel; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + unsigned long flags; + + channel = info->line; + + if (set & TIOCM_RTS) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; base_addr[CyMSVR1] = CyRTS; - local_irq_restore(flags); + local_irq_restore(flags); } - if (set & TIOCM_DTR){ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + if (set & TIOCM_DTR) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; /* CP('S');CP('2'); */ - base_addr[CyMSVR2] = CyDTR; + base_addr[CyMSVR2] = CyDTR; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); + printk("cyc: %d: raising DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); #endif - local_irq_restore(flags); + local_irq_restore(flags); } - if (clear & TIOCM_RTS){ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + if (clear & TIOCM_RTS) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; base_addr[CyMSVR1] = 0; - local_irq_restore(flags); + local_irq_restore(flags); } - if (clear & TIOCM_DTR){ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + if (clear & TIOCM_DTR) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; /* CP('C');CP('2'); */ - base_addr[CyMSVR2] = 0; + base_addr[CyMSVR2] = 0; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: dropping DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); + printk("cyc: %d: dropping DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); #endif - local_irq_restore(flags); + local_irq_restore(flags); } - return 0; -} /* set_modem_info */ - -static void -send_break( struct cyclades_port * info, int duration) -{ /* Let the transmit ISR take care of this (since it - requires stuffing characters into the output stream). - */ - info->x_break = duration; - if (!info->xmit_cnt ) { - start_xmit(info); - } -} /* send_break */ + return 0; +} /* set_modem_info */ + +static void send_break(struct cyclades_port *info, int duration) +{ /* Let the transmit ISR take care of this (since it + requires stuffing characters into the output stream). + */ + info->x_break = duration; + if (!info->xmit_cnt) { + start_xmit(info); + } +} /* send_break */ static int -get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) +get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) { - if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) - return -EFAULT; - info->mon.int_count = 0; - info->mon.char_count = 0; - info->mon.char_max = 0; - info->mon.char_last = 0; - return 0; + if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) + return -EFAULT; + info->mon.int_count = 0; + info->mon.char_count = 0; + info->mon.char_max = 0; + info->mon.char_last = 0; + return 0; } -static int -set_threshold(struct cyclades_port * info, unsigned long __user *arg) +static int set_threshold(struct cyclades_port *info, unsigned long __user * arg) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - unsigned long value; - int channel; - - if (get_user(value, arg)) - return -EFAULT; - - channel = info->line; - info->cor4 &= ~CyREC_FIFO; - info->cor4 |= value & CyREC_FIFO; - base_addr[CyCOR4] = info->cor4; - return 0; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + unsigned long value; + int channel; + + if (get_user(value, arg)) + return -EFAULT; + + channel = info->line; + info->cor4 &= ~CyREC_FIFO; + info->cor4 |= value & CyREC_FIFO; + base_addr[CyCOR4] = info->cor4; + return 0; } static int -get_threshold(struct cyclades_port * info, unsigned long __user *value) +get_threshold(struct cyclades_port *info, unsigned long __user * value) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; - unsigned long tmp; - - channel = info->line; - - tmp = base_addr[CyCOR4] & CyREC_FIFO; - return put_user(tmp,value); + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + unsigned long tmp; + + channel = info->line; + + tmp = base_addr[CyCOR4] & CyREC_FIFO; + return put_user(tmp, value); } static int -set_default_threshold(struct cyclades_port * info, unsigned long __user *arg) +set_default_threshold(struct cyclades_port *info, unsigned long __user * arg) { - unsigned long value; + unsigned long value; - if (get_user(value, arg)) - return -EFAULT; + if (get_user(value, arg)) + return -EFAULT; - info->default_threshold = value & 0x0f; - return 0; + info->default_threshold = value & 0x0f; + return 0; } static int -get_default_threshold(struct cyclades_port * info, unsigned long __user *value) +get_default_threshold(struct cyclades_port *info, unsigned long __user * value) { - return put_user(info->default_threshold,value); + return put_user(info->default_threshold, value); } -static int -set_timeout(struct cyclades_port * info, unsigned long __user *arg) +static int set_timeout(struct cyclades_port *info, unsigned long __user * arg) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; - unsigned long value; - - if (get_user(value, arg)) - return -EFAULT; - - channel = info->line; - - base_addr[CyRTPRL] = value & 0xff; - base_addr[CyRTPRH] = (value >> 8) & 0xff; - return 0; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + unsigned long value; + + if (get_user(value, arg)) + return -EFAULT; + + channel = info->line; + + base_addr[CyRTPRL] = value & 0xff; + base_addr[CyRTPRH] = (value >> 8) & 0xff; + return 0; } -static int -get_timeout(struct cyclades_port * info, unsigned long __user *value) +static int get_timeout(struct cyclades_port *info, unsigned long __user * value) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; - unsigned long tmp; - - channel = info->line; - - tmp = base_addr[CyRTPRL]; - return put_user(tmp,value); + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + unsigned long tmp; + + channel = info->line; + + tmp = base_addr[CyRTPRL]; + return put_user(tmp, value); } -static int -set_default_timeout(struct cyclades_port * info, unsigned long value) +static int set_default_timeout(struct cyclades_port *info, unsigned long value) { - info->default_timeout = value & 0xff; - return 0; + info->default_timeout = value & 0xff; + return 0; } static int -get_default_timeout(struct cyclades_port * info, unsigned long __user *value) +get_default_timeout(struct cyclades_port *info, unsigned long __user * value) { - return put_user(info->default_timeout,value); + return put_user(info->default_timeout, value); } static int -cy_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) +cy_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { - unsigned long val; - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int ret_val = 0; - void __user *argp = (void __user *)arg; + unsigned long val; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int ret_val = 0; + void __user *argp = (void __user *)arg; #ifdef SERIAL_DEBUG_OTHER - printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ -#endif - - switch (cmd) { - case CYGETMON: - ret_val = get_mon_info(info, argp); - break; - case CYGETTHRESH: - ret_val = get_threshold(info, argp); - break; - case CYSETTHRESH: - ret_val = set_threshold(info, argp); - break; - case CYGETDEFTHRESH: - ret_val = get_default_threshold(info, argp); - break; - case CYSETDEFTHRESH: - ret_val = set_default_threshold(info, argp); - break; - case CYGETTIMEOUT: - ret_val = get_timeout(info, argp); - break; - case CYSETTIMEOUT: - ret_val = set_timeout(info, argp); - break; - case CYGETDEFTIMEOUT: - ret_val = get_default_timeout(info, argp); - break; - case CYSETDEFTIMEOUT: - ret_val = set_default_timeout(info, (unsigned long)arg); - break; - case TCSBRK: /* SVID version: non-zero arg --> no break */ - ret_val = tty_check_change(tty); - if (ret_val) - break; - tty_wait_until_sent(tty,0); - if (!arg) - send_break(info, HZ/4); /* 1/4 second */ - break; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - ret_val = tty_check_change(tty); - if (ret_val) + printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ +#endif + + switch (cmd) { + case CYGETMON: + ret_val = get_mon_info(info, argp); + break; + case CYGETTHRESH: + ret_val = get_threshold(info, argp); + break; + case CYSETTHRESH: + ret_val = set_threshold(info, argp); + break; + case CYGETDEFTHRESH: + ret_val = get_default_threshold(info, argp); + break; + case CYSETDEFTHRESH: + ret_val = set_default_threshold(info, argp); + break; + case CYGETTIMEOUT: + ret_val = get_timeout(info, argp); + break; + case CYSETTIMEOUT: + ret_val = set_timeout(info, argp); + break; + case CYGETDEFTIMEOUT: + ret_val = get_default_timeout(info, argp); + break; + case CYSETDEFTIMEOUT: + ret_val = set_default_timeout(info, (unsigned long)arg); + break; + case TCSBRK: /* SVID version: non-zero arg --> no break */ + ret_val = tty_check_change(tty); + if (ret_val) + break; + tty_wait_until_sent(tty, 0); + if (!arg) + send_break(info, HZ / 4); /* 1/4 second */ + break; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + ret_val = tty_check_change(tty); + if (ret_val) + break; + tty_wait_until_sent(tty, 0); + send_break(info, arg ? arg * (HZ / 10) : HZ / 4); break; - tty_wait_until_sent(tty,0); - send_break(info, arg ? arg*(HZ/10) : HZ/4); - break; /* The following commands are incompletely implemented!!! */ - case TIOCGSOFTCAR: - ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp); - break; - case TIOCSSOFTCAR: - ret_val = get_user(val, (unsigned long __user *) argp); - if (ret_val) - break; - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); - break; - case TIOCGSERIAL: - ret_val = get_serial_info(info, argp); - break; - case TIOCSSERIAL: - ret_val = set_serial_info(info, argp); - break; - default: - ret_val = -ENOIOCTLCMD; - } + case TIOCGSOFTCAR: + ret_val = + put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long __user *)argp); + break; + case TIOCSSOFTCAR: + ret_val = get_user(val, (unsigned long __user *)argp); + if (ret_val) + break; + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); + break; + case TIOCGSERIAL: + ret_val = get_serial_info(info, argp); + break; + case TIOCSSERIAL: + ret_val = set_serial_info(info, argp); + break; + default: + ret_val = -ENOIOCTLCMD; + } #ifdef SERIAL_DEBUG_OTHER - printk("cy_ioctl done\n"); + printk("cy_ioctl done\n"); #endif - return ret_val; -} /* cy_ioctl */ - + return ret_val; +} /* cy_ioctl */ - - -static void -cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios) +static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; #ifdef SERIAL_DEBUG_OTHER - printk("cy_set_termios %s\n", tty->name); + printk("cy_set_termios %s\n", tty->name); #endif - if (tty->termios->c_cflag == old_termios->c_cflag) - return; - config_setup(info); + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + config_setup(info); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->stopped = 0; - cy_start(tty); - } + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->stopped = 0; + cy_start(tty); + } #ifdef tytso_patch_94Nov25_1726 - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); #endif +} /* cy_set_termios */ - return; -} /* cy_set_termios */ - - -static void -cy_close(struct tty_struct * tty, struct file * filp) +static void cy_close(struct tty_struct *tty, struct file *filp) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; /* CP('C'); */ #ifdef SERIAL_DEBUG_OTHER - printk("cy_close %s\n", tty->name); + printk("cy_close %s\n", tty->name); #endif - if (!info - || serial_paranoia_check(info, tty->name, "cy_close")){ - return; - } + if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { + return; + } #ifdef SERIAL_DEBUG_OPEN - printk("cy_close %s, count = %d\n", tty->name, info->count); -#endif - - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("cy_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } + printk("cy_close %s, count = %d\n", tty->name, info->count); +#endif + + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("cy_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1); + printk("cyc: %d: decrementing count to %d\n", __LINE__, + info->count - 1); #endif - if (--info->count < 0) { - printk("cy_close: bad serial port count for ttys%d: %d\n", - info->line, info->count); + if (--info->count < 0) { + printk("cy_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: setting count to 0\n", __LINE__); + printk("cyc: %d: setting count to 0\n", __LINE__); #endif - info->count = 0; - } - if (info->count) - return; - info->flags |= ASYNC_CLOSING; - if (info->flags & ASYNC_INITIALIZED) - tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ - shutdown(info); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - tty_ldisc_flush(tty); - info->event = 0; - info->tty = NULL; - if (info->blocked_open) { - if (info->close_delay) { - msleep_interruptible(jiffies_to_msecs(info->close_delay)); + info->count = 0; } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + if (info->count) + return; + info->flags |= ASYNC_CLOSING; + if (info->flags & ASYNC_INITIALIZED) + tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ + shutdown(info); + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + tty_ldisc_flush(tty); + info->event = 0; + info->tty = NULL; + if (info->blocked_open) { + if (info->close_delay) { + msleep_interruptible(jiffies_to_msecs + (info->close_delay)); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); #ifdef SERIAL_DEBUG_OTHER - printk("cy_close done\n"); + printk("cy_close done\n"); #endif - - return; -} /* cy_close */ +} /* cy_close */ /* * cy_hangup() --- called by tty_hangup() when a hangup is signaled. */ -void -cy_hangup(struct tty_struct *tty) +void cy_hangup(struct tty_struct *tty) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + #ifdef SERIAL_DEBUG_OTHER - printk("cy_hangup %s\n", tty->name); /* */ + printk("cy_hangup %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_hangup")) - return; - - shutdown(info); + if (serial_paranoia_check(info, tty->name, "cy_hangup")) + return; + + shutdown(info); #if 0 - info->event = 0; - info->count = 0; + info->event = 0; + info->count = 0; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: setting count to 0\n", __LINE__); + printk("cyc: %d: setting count to 0\n", __LINE__); #endif - info->tty = 0; + info->tty = 0; #endif - info->flags &= ~ASYNC_NORMAL_ACTIVE; - wake_up_interruptible(&info->open_wait); -} /* cy_hangup */ - - + info->flags &= ~ASYNC_NORMAL_ACTIVE; + wake_up_interruptible(&info->open_wait); +} /* cy_hangup */ /* * ------------------------------------------------------------ @@ -1827,177 +1796,180 @@ cy_hangup(struct tty_struct *tty) */ static int -block_til_ready(struct tty_struct *tty, struct file * filp, - struct cyclades_port *info) +block_til_ready(struct tty_struct *tty, struct file *filp, + struct cyclades_port *info) { - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int channel; - int retval; - volatile u_char *base_addr = (u_char *)BASE_ADDR; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (info->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&info->close_wait); - if (info->flags & ASYNC_HUP_NOTIFY){ - return -EAGAIN; - }else{ - return -ERESTARTSYS; - } - } - - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if (filp->f_flags & O_NONBLOCK) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * cy_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int channel; + int retval; + volatile u_char *base_addr = (u_char *) BASE_ADDR; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&info->close_wait); + if (info->flags & ASYNC_HUP_NOTIFY) { + return -EAGAIN; + } else { + return -ERESTARTSYS; + } + } + + /* + * If non-blocking mode is set, then make the check up front + * and then exit. + */ + if (filp->f_flags & O_NONBLOCK) { + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * cy_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: %s, count = %d\n", - tty->name, info->count);/**/ + printk("block_til_ready before block: %s, count = %d\n", + tty->name, info->count); + /**/ #endif - info->count--; + info->count--; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); + printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); #endif - info->blocked_open++; + info->blocked_open++; - channel = info->line; + channel = info->line; - while (1) { - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; - base_addr[CyMSVR1] = CyRTS; + while (1) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + base_addr[CyMSVR1] = CyRTS; /* CP('S');CP('4'); */ - base_addr[CyMSVR2] = CyDTR; + base_addr[CyMSVR2] = CyDTR; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); -#endif - local_irq_restore(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) - || !(info->flags & ASYNC_INITIALIZED) ){ - if (info->flags & ASYNC_HUP_NOTIFY) { - retval = -EAGAIN; - }else{ - retval = -ERESTARTSYS; - } - break; - } - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; + printk("cyc: %d: raising DTR\n", __LINE__); + printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], + base_addr[CyMSVR2]); +#endif + local_irq_restore(flags); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) + || !(info->flags & ASYNC_INITIALIZED)) { + if (info->flags & ASYNC_HUP_NOTIFY) { + retval = -EAGAIN; + } else { + retval = -ERESTARTSYS; + } + break; + } + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; /* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */ - if (!(info->flags & ASYNC_CLOSING) - && (C_CLOCAL(tty) - || (base_addr[CyMSVR1] & CyDCD))) { - local_irq_restore(flags); - break; - } - local_irq_restore(flags); - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } + if (!(info->flags & ASYNC_CLOSING) + && (C_CLOCAL(tty) + || (base_addr[CyMSVR1] & CyDCD))) { + local_irq_restore(flags); + break; + } + local_irq_restore(flags); + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: %s, count = %d\n", - tty->name, info->count);/**/ -#endif - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)){ - info->count++; + printk("block_til_ready blocking: %s, count = %d\n", + tty->name, info->count); + /**/ +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) { + info->count++; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); + printk("cyc: %d: incrementing count to %d\n", __LINE__, + info->count); #endif - } - info->blocked_open--; + } + info->blocked_open--; #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: %s, count = %d\n", - tty->name, info->count);/**/ + printk("block_til_ready after blocking: %s, count = %d\n", + tty->name, info->count); + /**/ #endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} /* block_til_ready */ + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} /* block_til_ready */ /* * This routine is called whenever a serial port is opened. It * performs the serial-specific initialization for the tty structure. */ -int -cy_open(struct tty_struct *tty, struct file * filp) +int cy_open(struct tty_struct *tty, struct file *filp) { - struct cyclades_port *info; - int retval, line; + struct cyclades_port *info; + int retval, line; /* CP('O'); */ - line = tty->index; - if ((line < 0) || (NR_PORTS <= line)){ - return -ENODEV; - } - info = &cy_port[line]; - if (info->line < 0){ - return -ENODEV; - } + line = tty->index; + if ((line < 0) || (NR_PORTS <= line)) { + return -ENODEV; + } + info = &cy_port[line]; + if (info->line < 0) { + return -ENODEV; + } #ifdef SERIAL_DEBUG_OTHER - printk("cy_open %s\n", tty->name); /* */ + printk("cy_open %s\n", tty->name); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_open")){ - return -ENODEV; - } + if (serial_paranoia_check(info, tty->name, "cy_open")) { + return -ENODEV; + } #ifdef SERIAL_DEBUG_OPEN - printk("cy_open %s, count = %d\n", tty->name, info->count);/**/ + printk("cy_open %s, count = %d\n", tty->name, info->count); + /**/ #endif - info->count++; + info->count++; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); + printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); #endif - tty->driver_data = info; - info->tty = tty; + tty->driver_data = info; + info->tty = tty; - /* - * Start up serial port - */ - retval = startup(info); - if (retval){ - return retval; - } + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + return retval; + } - retval = block_til_ready(tty, filp, info); - if (retval) { + retval = block_til_ready(tty, filp, info); + if (retval) { #ifdef SERIAL_DEBUG_OPEN - printk("cy_open returning after block_til_ready with %d\n", - retval); + printk("cy_open returning after block_til_ready with %d\n", + retval); #endif - return retval; - } - + return retval; + } #ifdef SERIAL_DEBUG_OPEN - printk("cy_open done\n");/**/ + printk("cy_open done\n"); + /**/ #endif - return 0; -} /* cy_open */ - - + return 0; +} /* cy_open */ /* * --------------------------------------------------------------------- @@ -2012,11 +1984,10 @@ cy_open(struct tty_struct *tty, struct file * filp) * number, and identifies which options were configured into this * driver. */ -static void -show_version(void) +static void show_version(void) { - printk("MVME166/167 cd2401 driver\n"); -} /* show_version */ + printk("MVME166/167 cd2401 driver\n"); +} /* show_version */ /* initialize chips on card -- return number of valid chips (which is number of ports/4) */ @@ -2030,10 +2001,9 @@ show_version(void) * ... I wonder what I should do if this fails ... */ -void -mvme167_serial_console_setup(int cflag) +void mvme167_serial_console_setup(int cflag) { - volatile unsigned char* base_addr = (u_char *)BASE_ADDR; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; int ch; u_char spd; u_char rcor, rbpr, badspeed = 0; @@ -2062,21 +2032,21 @@ mvme167_serial_console_setup(int cflag) /* OK, we have chosen a speed, now reset and reinitialise */ - my_udelay(20000L); /* Allow time for any active o/p to complete */ - if(base_addr[CyCCR] != 0x00){ - local_irq_restore(flags); - /* printk(" chip is never idle (CCR != 0)\n"); */ - return; - } + my_udelay(20000L); /* Allow time for any active o/p to complete */ + if (base_addr[CyCCR] != 0x00) { + local_irq_restore(flags); + /* printk(" chip is never idle (CCR != 0)\n"); */ + return; + } - base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */ - my_udelay(1000L); + base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */ + my_udelay(1000L); - if(base_addr[CyGFRCR] == 0x00){ - local_irq_restore(flags); - /* printk(" chip is not responding (GFRCR stayed 0)\n"); */ - return; - } + if (base_addr[CyGFRCR] == 0x00) { + local_irq_restore(flags); + /* printk(" chip is not responding (GFRCR stayed 0)\n"); */ + return; + } /* * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms @@ -2085,9 +2055,9 @@ mvme167_serial_console_setup(int cflag) base_addr[CyTPR] = 10; - base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */ - base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */ - base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */ + base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */ + base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */ + base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */ /* * Attempt to set up all channels to something reasonable, and @@ -2095,11 +2065,11 @@ mvme167_serial_console_setup(int cflag) * the ammount of fiddling we have to do in normal running. */ - for (ch = 3; ch >= 0 ; ch--) { - base_addr[CyCAR] = (u_char)ch; + for (ch = 3; ch >= 0; ch--) { + base_addr[CyCAR] = (u_char) ch; base_addr[CyIER] = 0; base_addr[CyCMR] = CyASYNC; - base_addr[CyLICR] = (u_char)ch << 2; + base_addr[CyLICR] = (u_char) ch << 2; base_addr[CyLIVR] = 0x5c; base_addr[CyTCOR] = baud_co[spd]; base_addr[CyTBPR] = baud_bpr[spd]; @@ -2118,29 +2088,30 @@ mvme167_serial_console_setup(int cflag) base_addr[CyCOR7] = 0; base_addr[CyRTPRL] = 2; base_addr[CyRTPRH] = 0; - base_addr[CyMSVR1] = 0; - base_addr[CyMSVR2] = 0; - write_cy_cmd(base_addr,CyINIT_CHAN|CyDIS_RCVR|CyDIS_XMTR); + base_addr[CyMSVR1] = 0; + base_addr[CyMSVR2] = 0; + write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR); } /* * Now do specials for channel zero.... */ - base_addr[CyMSVR1] = CyRTS; - base_addr[CyMSVR2] = CyDTR; + base_addr[CyMSVR1] = CyRTS; + base_addr[CyMSVR2] = CyDTR; base_addr[CyIER] = CyRxData; - write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR); + write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR); local_irq_restore(flags); my_udelay(20000L); /* Let it all settle down */ - printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]); + printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]); if (badspeed) - printk(" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n", - rcor >> 5, rbpr); -} /* serial_console_init */ + printk + (" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n", + rcor >> 5, rbpr); +} /* serial_console_init */ static const struct tty_operations cy_ops = { .open = cy_open, @@ -2161,6 +2132,7 @@ static const struct tty_operations cy_ops = { .tiocmget = cy_tiocmget, .tiocmset = cy_tiocmset, }; + /* The serial driver boot-time initialization code! Hardware I/O ports are mapped to character special devices on a first found, first allocated manner. That is, this code searches @@ -2177,214 +2149,214 @@ static const struct tty_operations cy_ops = { If there are more cards with more ports than have been statically allocated above, a warning is printed and the extra ports are ignored. */ -static int __init -serial167_init(void) +static int __init serial167_init(void) { - struct cyclades_port *info; - int ret = 0; - int good_ports = 0; - int port_num = 0; - int index; - int DefSpeed; + struct cyclades_port *info; + int ret = 0; + int good_ports = 0; + int port_num = 0; + int index; + int DefSpeed; #ifdef notyet - struct sigaction sa; + struct sigaction sa; #endif - if (!(mvme16x_config &MVME16x_CONFIG_GOT_CD2401)) - return 0; + if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401)) + return 0; - cy_serial_driver = alloc_tty_driver(NR_PORTS); - if (!cy_serial_driver) - return -ENOMEM; + cy_serial_driver = alloc_tty_driver(NR_PORTS); + if (!cy_serial_driver) + return -ENOMEM; #if 0 -scrn[1] = '\0'; + scrn[1] = '\0'; #endif - show_version(); + show_version(); - /* Has "console=0,9600n8" been used in bootinfo to change speed? */ - if (serial_console_cflag) - DefSpeed = serial_console_cflag & 0017; - else { - DefSpeed = initial_console_speed; - serial_console_info = &cy_port[0]; - serial_console_cflag = DefSpeed | CS8; + /* Has "console=0,9600n8" been used in bootinfo to change speed? */ + if (serial_console_cflag) + DefSpeed = serial_console_cflag & 0017; + else { + DefSpeed = initial_console_speed; + serial_console_info = &cy_port[0]; + serial_console_cflag = DefSpeed | CS8; #if 0 - serial_console = 64; /*callout_driver.minor_start*/ -#endif - } - - /* Initialize the tty_driver structure */ - - cy_serial_driver->owner = THIS_MODULE; - cy_serial_driver->name = "ttyS"; - cy_serial_driver->major = TTY_MAJOR; - cy_serial_driver->minor_start = 64; - cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; - cy_serial_driver->init_termios = tty_std_termios; - cy_serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(cy_serial_driver, &cy_ops); + serial_console = 64; /*callout_driver.minor_start */ +#endif + } - ret = tty_register_driver(cy_serial_driver); - if (ret) { - printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n"); - put_tty_driver(cy_serial_driver); - return ret; - } + /* Initialize the tty_driver structure */ - port_num = 0; - info = cy_port; - for (index = 0; index < 1; index++) { + cy_serial_driver->owner = THIS_MODULE; + cy_serial_driver->name = "ttyS"; + cy_serial_driver->major = TTY_MAJOR; + cy_serial_driver->minor_start = 64; + cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; + cy_serial_driver->init_termios = tty_std_termios; + cy_serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(cy_serial_driver, &cy_ops); + + ret = tty_register_driver(cy_serial_driver); + if (ret) { + printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n"); + put_tty_driver(cy_serial_driver); + return ret; + } - good_ports = 4; + port_num = 0; + info = cy_port; + for (index = 0; index < 1; index++) { - if(port_num < NR_PORTS){ - while( good_ports-- && port_num < NR_PORTS){ + good_ports = 4; + + if (port_num < NR_PORTS) { + while (good_ports-- && port_num < NR_PORTS) { /*** initialize port ***/ - info->magic = CYCLADES_MAGIC; - info->type = PORT_CIRRUS; - info->card = index; - info->line = port_num; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - info->xmit_fifo_size = 12; - info->cor1 = CyPARITY_NONE|Cy_8_BITS; - info->cor2 = CyETC; - info->cor3 = Cy_1_STOP; - info->cor4 = 0x08; /* _very_ small receive threshold */ - info->cor5 = 0; - info->cor6 = 0; - info->cor7 = 0; - info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */ - info->tco = baud_co[DefSpeed]; /* Tx CO */ - info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */ - info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ - info->close_delay = 0; - info->x_char = 0; - info->event = 0; - info->count = 0; + info->magic = CYCLADES_MAGIC; + info->type = PORT_CIRRUS; + info->card = index; + info->line = port_num; + info->flags = STD_COM_FLAGS; + info->tty = NULL; + info->xmit_fifo_size = 12; + info->cor1 = CyPARITY_NONE | Cy_8_BITS; + info->cor2 = CyETC; + info->cor3 = Cy_1_STOP; + info->cor4 = 0x08; /* _very_ small receive threshold */ + info->cor5 = 0; + info->cor6 = 0; + info->cor7 = 0; + info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */ + info->tco = baud_co[DefSpeed]; /* Tx CO */ + info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */ + info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ + info->close_delay = 0; + info->x_char = 0; + info->event = 0; + info->count = 0; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: setting count to 0\n", __LINE__); -#endif - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - /* info->session */ - /* info->pgrp */ + printk("cyc: %d: setting count to 0\n", + __LINE__); +#endif + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + INIT_WORK(&info->tqueue, do_softint); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + /* info->session */ + /* info->pgrp */ /*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/ - info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK - | CyPARITY| CyFRAME| CyOVERRUN; - /* info->timeout */ - - printk("ttyS%d ", info->line); - port_num++;info++; - if(!(port_num & 7)){ - printk("\n "); + info->read_status_mask = + CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY | + CyFRAME | CyOVERRUN; + /* info->timeout */ + + printk("ttyS%d ", info->line); + port_num++; + info++; + if (!(port_num & 7)) { + printk("\n "); + } + } } - } - } - printk("\n"); - } - while( port_num < NR_PORTS){ - info->line = -1; - port_num++;info++; - } + printk("\n"); + } + while (port_num < NR_PORTS) { + info->line = -1; + port_num++; + info++; + } #ifdef CONFIG_REMOTE_DEBUG - debug_setup(); -#endif - ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, - "cd2401_errors", cd2401_rxerr_interrupt); - if (ret) { - printk(KERN_ERR "Could't get cd2401_errors IRQ"); - goto cleanup_serial_driver; - } - - ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, - "cd2401_modem", cd2401_modem_interrupt); - if (ret) { - printk(KERN_ERR "Could't get cd2401_modem IRQ"); - goto cleanup_irq_cd2401_errors; - } - - ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, - "cd2401_txints", cd2401_tx_interrupt); - if (ret) { - printk(KERN_ERR "Could't get cd2401_txints IRQ"); - goto cleanup_irq_cd2401_modem; - } - - ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, - "cd2401_rxints", cd2401_rx_interrupt); - if (ret) { - printk(KERN_ERR "Could't get cd2401_rxints IRQ"); - goto cleanup_irq_cd2401_txints; - } - - /* Now we have registered the interrupt handlers, allow the interrupts */ - - pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */ - pcc2chip[PccSCCTICR] = 0x15; - pcc2chip[PccSCCRICR] = 0x15; - - pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */ - - return 0; + debug_setup(); +#endif + ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, + "cd2401_errors", cd2401_rxerr_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_errors IRQ"); + goto cleanup_serial_driver; + } + + ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, + "cd2401_modem", cd2401_modem_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_modem IRQ"); + goto cleanup_irq_cd2401_errors; + } + + ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, + "cd2401_txints", cd2401_tx_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_txints IRQ"); + goto cleanup_irq_cd2401_modem; + } + + ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, + "cd2401_rxints", cd2401_rx_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_rxints IRQ"); + goto cleanup_irq_cd2401_txints; + } + + /* Now we have registered the interrupt handlers, allow the interrupts */ + + pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */ + pcc2chip[PccSCCTICR] = 0x15; + pcc2chip[PccSCCRICR] = 0x15; + + pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */ + + return 0; cleanup_irq_cd2401_txints: - free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt); + free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt); cleanup_irq_cd2401_modem: - free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); + free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); cleanup_irq_cd2401_errors: - free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt); + free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt); cleanup_serial_driver: - if (tty_unregister_driver(cy_serial_driver)) - printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n"); - put_tty_driver(cy_serial_driver); - return ret; -} /* serial167_init */ + if (tty_unregister_driver(cy_serial_driver)) + printk(KERN_ERR + "Couldn't unregister MVME166/7 serial driver\n"); + put_tty_driver(cy_serial_driver); + return ret; +} /* serial167_init */ module_init(serial167_init); - #ifdef CYCLOM_SHOW_STATUS -static void -show_status(int line_num) +static void show_status(int line_num) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int channel; - struct cyclades_port * info; - unsigned long flags; - - info = &cy_port[line_num]; - channel = info->line; - printk(" channel %d\n", channel);/**/ - - printk(" cy_port\n"); - printk(" card line flags = %d %d %x\n", - info->card, info->line, info->flags); - printk(" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n", - (long)info->tty, info->read_status_mask, - info->timeout, info->xmit_fifo_size); - printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n", - info->cor1, info->cor2, info->cor3, info->cor4, info->cor5, - info->cor6, info->cor7); - printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", - info->tbpr, info->tco, info->rbpr, info->rco); - printk(" close_delay event count = %d %d %d\n", - info->close_delay, info->event, info->count); - printk(" x_char blocked_open = %x %x\n", - info->x_char, info->blocked_open); - printk(" open_wait = %lx %lx %lx\n", - (long)info->open_wait); - - - local_irq_save(flags); + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + struct cyclades_port *info; + unsigned long flags; + + info = &cy_port[line_num]; + channel = info->line; + printk(" channel %d\n", channel); + /**/ printk(" cy_port\n"); + printk(" card line flags = %d %d %x\n", + info->card, info->line, info->flags); + printk + (" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n", + (long)info->tty, info->read_status_mask, info->timeout, + info->xmit_fifo_size); + printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n", + info->cor1, info->cor2, info->cor3, info->cor4, info->cor5, + info->cor6, info->cor7); + printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco, + info->rbpr, info->rco); + printk(" close_delay event count = %d %d %d\n", info->close_delay, + info->event, info->count); + printk(" x_char blocked_open = %x %x\n", info->x_char, + info->blocked_open); + printk(" open_wait = %lx %lx %lx\n", (long)info->open_wait); + + local_irq_save(flags); /* Global Registers */ @@ -2398,7 +2370,7 @@ show_status(int line_num) printk(" CyMIR %x\n", base_addr[CyMIR]); printk(" CyTPR %x\n", base_addr[CyTPR]); - base_addr[CyCAR] = (u_char)channel; + base_addr[CyCAR] = (u_char) channel; /* Virtual Registers */ @@ -2442,11 +2414,10 @@ show_status(int line_num) printk(" CyTBPR %x\n", base_addr[CyTBPR]); printk(" CyTCOR %x\n", base_addr[CyTCOR]); - local_irq_restore(flags); -} /* show_status */ + local_irq_restore(flags); +} /* show_status */ #endif - #if 0 /* Dummy routine in mvme16x/config.c for now */ @@ -2459,61 +2430,67 @@ void console_setup(char *str, int *ints) int cflag = 0; /* Sanity check. */ - if (ints[0] > 3 || ints[1] > 3) return; + if (ints[0] > 3 || ints[1] > 3) + return; /* Get baud, bits and parity */ baud = 2400; bits = 8; parity = 'n'; - if (ints[2]) baud = ints[2]; + if (ints[2]) + baud = ints[2]; if ((s = strchr(str, ','))) { do { s++; - } while(*s >= '0' && *s <= '9'); - if (*s) parity = *s++; - if (*s) bits = *s - '0'; + } while (*s >= '0' && *s <= '9'); + if (*s) + parity = *s++; + if (*s) + bits = *s - '0'; } /* Now construct a cflag setting. */ - switch(baud) { - case 1200: - cflag |= B1200; - break; - case 9600: - cflag |= B9600; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 2400: - default: - cflag |= B2400; - break; + switch (baud) { + case 1200: + cflag |= B1200; + break; + case 9600: + cflag |= B9600; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 2400: + default: + cflag |= B2400; + break; } - switch(bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; + switch (bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; } - switch(parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; + switch (parity) { + case 'o': + case 'O': + cflag |= PARODD; + break; + case 'e': + case 'E': + cflag |= PARENB; + break; } serial_console_info = &cy_port[ints[1]]; serial_console_cflag = cflag; - serial_console = ints[1] + 64; /*callout_driver.minor_start*/ + serial_console = ints[1] + 64; /*callout_driver.minor_start */ } #endif @@ -2532,9 +2509,10 @@ void console_setup(char *str, int *ints) * The console must be locked when we get here. */ -void serial167_console_write(struct console *co, const char *str, unsigned count) +void serial167_console_write(struct console *co, const char *str, + unsigned count) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; unsigned long flags; volatile u_char sink; u_char ier; @@ -2547,7 +2525,7 @@ void serial167_console_write(struct console *co, const char *str, unsigned count /* Ensure transmitter is enabled! */ port = 0; - base_addr[CyCAR] = (u_char)port; + base_addr[CyCAR] = (u_char) port; while (base_addr[CyCCR]) ; base_addr[CyCCR] = CyENB_XMTR; @@ -2556,8 +2534,7 @@ void serial167_console_write(struct console *co, const char *str, unsigned count base_addr[CyIER] = CyTxMpty; while (1) { - if (pcc2chip[PccSCCTICR] & 0x20) - { + if (pcc2chip[PccSCCTICR] & 0x20) { /* We have a Tx int. Acknowledge it */ sink = pcc2chip[PccTPIACKR]; if ((base_addr[CyLICR] >> 2) == port) { @@ -2571,18 +2548,15 @@ void serial167_console_write(struct console *co, const char *str, unsigned count str++; i++; do_lf = 0; - } - else if (*str == '\n') { + } else if (*str == '\n') { base_addr[CyTDR] = '\r'; do_lf = 1; - } - else { + } else { base_addr[CyTDR] = *str++; i++; } base_addr[CyTEOIR] = 0; - } - else + } else base_addr[CyTEOIR] = CyNOTRANS; } } @@ -2592,45 +2566,44 @@ void serial167_console_write(struct console *co, const char *str, unsigned count local_irq_restore(flags); } -static struct tty_driver *serial167_console_device(struct console *c, int *index) +static struct tty_driver *serial167_console_device(struct console *c, + int *index) { *index = c->index; return cy_serial_driver; } - static int __init serial167_console_setup(struct console *co, char *options) { return 0; } - static struct console sercons = { - .name = "ttyS", - .write = serial167_console_write, - .device = serial167_console_device, - .setup = serial167_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, + .name = "ttyS", + .write = serial167_console_write, + .device = serial167_console_device, + .setup = serial167_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; - static int __init serial167_console_init(void) { if (vme_brdtype == VME_TYPE_MVME166 || - vme_brdtype == VME_TYPE_MVME167 || - vme_brdtype == VME_TYPE_MVME177) { + vme_brdtype == VME_TYPE_MVME167 || + vme_brdtype == VME_TYPE_MVME177) { mvme167_serial_console_setup(0); register_console(&sercons); } return 0; } + console_initcall(serial167_console_init); #ifdef CONFIG_REMOTE_DEBUG -void putDebugChar (int c) +void putDebugChar(int c) { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; unsigned long flags; volatile u_char sink; u_char ier; @@ -2641,7 +2614,7 @@ void putDebugChar (int c) /* Ensure transmitter is enabled! */ port = DEBUG_PORT; - base_addr[CyCAR] = (u_char)port; + base_addr[CyCAR] = (u_char) port; while (base_addr[CyCCR]) ; base_addr[CyCCR] = CyENB_XMTR; @@ -2650,16 +2623,14 @@ void putDebugChar (int c) base_addr[CyIER] = CyTxMpty; while (1) { - if (pcc2chip[PccSCCTICR] & 0x20) - { + if (pcc2chip[PccSCCTICR] & 0x20) { /* We have a Tx int. Acknowledge it */ sink = pcc2chip[PccTPIACKR]; if ((base_addr[CyLICR] >> 2) == port) { base_addr[CyTDR] = c; base_addr[CyTEOIR] = 0; break; - } - else + } else base_addr[CyTEOIR] = CyNOTRANS; } } @@ -2671,7 +2642,7 @@ void putDebugChar (int c) int getDebugChar() { - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; unsigned long flags; volatile u_char sink; u_char ier; @@ -2693,7 +2664,7 @@ int getDebugChar() /* Ensure receiver is enabled! */ port = DEBUG_PORT; - base_addr[CyCAR] = (u_char)port; + base_addr[CyCAR] = (u_char) port; #if 0 while (base_addr[CyCCR]) ; @@ -2703,31 +2674,30 @@ int getDebugChar() base_addr[CyIER] = CyRxData; while (1) { - if (pcc2chip[PccSCCRICR] & 0x20) - { + if (pcc2chip[PccSCCRICR] & 0x20) { /* We have a Rx int. Acknowledge it */ sink = pcc2chip[PccRPIACKR]; if ((base_addr[CyLICR] >> 2) == port) { int cnt = base_addr[CyRFOC]; - while (cnt-- > 0) - { + while (cnt-- > 0) { c = base_addr[CyRDR]; if (c == 0) - printk ("!! debug char is null (cnt=%d) !!", cnt); + printk + ("!! debug char is null (cnt=%d) !!", + cnt); else - queueDebugChar (c); + queueDebugChar(c); } base_addr[CyREOIR] = 0; i = debugiq.out; if (i == debugiq.in) - panic ("Debug input queue empty!"); + panic("Debug input queue empty!"); c = debugiq.buf[i]; if (++i == DEBUG_LEN) i = 0; debugiq.out = i; break; - } - else + } else base_addr[CyREOIR] = CyNOTRANS; } } @@ -2739,7 +2709,7 @@ int getDebugChar() return (c); } -void queueDebugChar (int c) +void queueDebugChar(int c) { int i; @@ -2751,73 +2721,71 @@ void queueDebugChar (int c) debugiq.in = i; } -static void -debug_setup() +static void debug_setup() { - unsigned long flags; - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - int i, cflag; + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int i, cflag; - cflag = B19200; + cflag = B19200; - local_irq_save(flags); + local_irq_save(flags); - for (i = 0; i < 4; i++) - { - base_addr[CyCAR] = i; - base_addr[CyLICR] = i << 2; - } + for (i = 0; i < 4; i++) { + base_addr[CyCAR] = i; + base_addr[CyLICR] = i << 2; + } - debugiq.in = debugiq.out = 0; + debugiq.in = debugiq.out = 0; - base_addr[CyCAR] = DEBUG_PORT; + base_addr[CyCAR] = DEBUG_PORT; - /* baud rate */ - i = cflag & CBAUD; + /* baud rate */ + i = cflag & CBAUD; - base_addr[CyIER] = 0; + base_addr[CyIER] = 0; - base_addr[CyCMR] = CyASYNC; - base_addr[CyLICR] = DEBUG_PORT << 2; - base_addr[CyLIVR] = 0x5c; + base_addr[CyCMR] = CyASYNC; + base_addr[CyLICR] = DEBUG_PORT << 2; + base_addr[CyLIVR] = 0x5c; - /* tx and rx baud rate */ + /* tx and rx baud rate */ - base_addr[CyTCOR] = baud_co[i]; - base_addr[CyTBPR] = baud_bpr[i]; - base_addr[CyRCOR] = baud_co[i] >> 5; - base_addr[CyRBPR] = baud_bpr[i]; + base_addr[CyTCOR] = baud_co[i]; + base_addr[CyTBPR] = baud_bpr[i]; + base_addr[CyRCOR] = baud_co[i] >> 5; + base_addr[CyRBPR] = baud_bpr[i]; - /* set line characteristics according configuration */ + /* set line characteristics according configuration */ - base_addr[CySCHR1] = 0; - base_addr[CySCHR2] = 0; - base_addr[CySCRL] = 0; - base_addr[CySCRH] = 0; - base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE; - base_addr[CyCOR2] = 0; - base_addr[CyCOR3] = Cy_1_STOP; - base_addr[CyCOR4] = baud_cor4[i]; - base_addr[CyCOR5] = 0; - base_addr[CyCOR6] = 0; - base_addr[CyCOR7] = 0; + base_addr[CySCHR1] = 0; + base_addr[CySCHR2] = 0; + base_addr[CySCRL] = 0; + base_addr[CySCRH] = 0; + base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE; + base_addr[CyCOR2] = 0; + base_addr[CyCOR3] = Cy_1_STOP; + base_addr[CyCOR4] = baud_cor4[i]; + base_addr[CyCOR5] = 0; + base_addr[CyCOR6] = 0; + base_addr[CyCOR7] = 0; - write_cy_cmd(base_addr,CyINIT_CHAN); - write_cy_cmd(base_addr,CyENB_RCVR); + write_cy_cmd(base_addr, CyINIT_CHAN); + write_cy_cmd(base_addr, CyENB_RCVR); - base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */ + base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */ - base_addr[CyRTPRL] = 2; - base_addr[CyRTPRH] = 0; + base_addr[CyRTPRL] = 2; + base_addr[CyRTPRH] = 0; - base_addr[CyMSVR1] = CyRTS; - base_addr[CyMSVR2] = CyDTR; + base_addr[CyMSVR1] = CyRTS; + base_addr[CyMSVR2] = CyDTR; - base_addr[CyIER] = CyRxData; + base_addr[CyIER] = CyRxData; - local_irq_restore(flags); + local_irq_restore(flags); -} /* debug_setup */ +} /* debug_setup */ #endif diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 20946f5..baf7234 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -459,10 +459,9 @@ void missed_irq (unsigned long data) if (irq) { printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); sx_interrupt (((struct specialix_board *)data)->irq, - (void*)data, NULL); + (void*)data); } - missed_irq_timer.expires = jiffies + sx_poll; - add_timer (&missed_irq_timer); + mod_timer(&missed_irq_timer, jiffies + sx_poll); } #endif @@ -597,11 +596,8 @@ static int sx_probe(struct specialix_board *bp) dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); #ifdef SPECIALIX_TIMER - init_timer (&missed_irq_timer); - missed_irq_timer.function = missed_irq; - missed_irq_timer.data = (unsigned long) bp; - missed_irq_timer.expires = jiffies + sx_poll; - add_timer (&missed_irq_timer); + setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp); + mod_timer(&missed_irq_timer, jiffies + sx_poll); #endif printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", @@ -2350,10 +2346,8 @@ static void do_softint(struct work_struct *work) return; } - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) tty_wakeup(tty); - //wake_up_interruptible(&tty->write_wait); - } func_exit(); } @@ -2561,7 +2555,7 @@ static void __exit specialix_exit_module(void) if (sx_board[i].flags & SX_BOARD_PRESENT) sx_release_io_range(&sx_board[i]); #ifdef SPECIALIX_TIMER - del_timer (&missed_irq_timer); + del_timer_sync(&missed_irq_timer); #endif func_exit(); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 3fa625d..ce4db6f 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1148,10 +1148,8 @@ static void mgsl_bh_transmit(struct mgsl_struct *info) printk( "%s(%d):mgsl_bh_transmit() entry on %s\n", __FILE__,__LINE__,info->device_name); - if (tty) { + if (tty) tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } /* if transmitter idle and loopmode_send_done_requested * then start echoing RxD to TxD @@ -1800,9 +1798,7 @@ static int startup(struct mgsl_struct * info) memset(&info->icount, 0, sizeof(info->icount)); - init_timer(&info->tx_timer); - info->tx_timer.data = (unsigned long)info; - info->tx_timer.function = mgsl_tx_timeout; + setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info); /* Allocate and claim adapter resources */ retval = mgsl_claim_resources(info); @@ -1853,7 +1849,7 @@ static void shutdown(struct mgsl_struct * info) wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); - del_timer(&info->tx_timer); + del_timer_sync(&info->tx_timer); if (info->xmit_buf) { free_page((unsigned long) info->xmit_buf); @@ -2340,7 +2336,6 @@ static void mgsl_flush_buffer(struct tty_struct *tty) del_timer(&info->tx_timer); spin_unlock_irqrestore(&info->irq_spinlock,flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -5713,8 +5708,8 @@ static void usc_start_transmitter( struct mgsl_struct *info ) usc_TCmd( info, TCmd_SendFrame ); - info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); - add_timer(&info->tx_timer); + mod_timer(&info->tx_timer, jiffies + + msecs_to_jiffies(5000)); } info->tx_active = 1; } diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 792c79c..0a367cd 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1045,7 +1045,6 @@ static void flush_buffer(struct tty_struct *tty) info->tx_count = 0; spin_unlock_irqrestore(&info->lock,flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -1826,8 +1825,7 @@ static void rx_async(struct slgt_info *info) if (i < count) { /* receive buffer not completed */ info->rbuf_index += i; - info->rx_timer.expires = jiffies + 1; - add_timer(&info->rx_timer); + mod_timer(&info->rx_timer, jiffies + 1); break; } @@ -1933,10 +1931,8 @@ static void bh_transmit(struct slgt_info *info) struct tty_struct *tty = info->tty; DBGBH(("%s bh_transmit\n", info->device_name)); - if (tty) { + if (tty) tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } } static void dsr_change(struct slgt_info *info) @@ -3343,13 +3339,8 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev info->adapter_num = adapter_num; info->port_num = port_num; - init_timer(&info->tx_timer); - info->tx_timer.data = (unsigned long)info; - info->tx_timer.function = tx_timeout; - - init_timer(&info->rx_timer); - info->rx_timer.data = (unsigned long)info; - info->rx_timer.function = rx_timeout; + setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); + setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info); /* Copy configuration info to device instance data */ info->pdev = pdev; @@ -3797,10 +3788,9 @@ static void tx_start(struct slgt_info *info) } } - if (info->params.mode == MGSL_MODE_HDLC) { - info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); - add_timer(&info->tx_timer); - } + if (info->params.mode == MGSL_MODE_HDLC) + mod_timer(&info->tx_timer, jiffies + + msecs_to_jiffies(5000)); } else { tdma_reset(info); /* set 1st descriptor address */ diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8f4d67a..ef93d05 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1258,7 +1258,6 @@ static void flush_buffer(struct tty_struct *tty) del_timer(&info->tx_timer); spin_unlock_irqrestore(&info->lock,flags); - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -2127,10 +2126,8 @@ void bh_transmit(SLMP_INFO *info) printk( "%s(%d):%s bh_transmit() entry\n", __FILE__,__LINE__,info->device_name); - if (tty) { + if (tty) tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } } void bh_status(SLMP_INFO *info) @@ -2747,8 +2744,7 @@ static int startup(SLMP_INFO * info) change_params(info); - info->status_timer.expires = jiffies + msecs_to_jiffies(10); - add_timer(&info->status_timer); + mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); @@ -3844,13 +3840,9 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) info->bus_type = MGSL_BUS_TYPE_PCI; info->irq_flags = IRQF_SHARED; - init_timer(&info->tx_timer); - info->tx_timer.data = (unsigned long)info; - info->tx_timer.function = tx_timeout; - - init_timer(&info->status_timer); - info->status_timer.data = (unsigned long)info; - info->status_timer.function = status_timeout; + setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); + setup_timer(&info->status_timer, status_timeout, + (unsigned long)info); /* Store the PCI9050 misc control register value because a flaw * in the PCI9050 prevents LCR registers from being read if @@ -4294,8 +4286,8 @@ void tx_start(SLMP_INFO *info) write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ write_reg(info, TXDMA + DSR, 0xf2); /* clear Tx DMA IRQs, enable Tx DMA */ - info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); - add_timer(&info->tx_timer); + mod_timer(&info->tx_timer, jiffies + + msecs_to_jiffies(5000)); } else { tx_load_fifo(info); @@ -5577,10 +5569,7 @@ void status_timeout(unsigned long context) if (status) isr_io_pin(info,status); - info->status_timer.data = (unsigned long)info; - info->status_timer.function = status_timeout; - info->status_timer.expires = jiffies + msecs_to_jiffies(10); - add_timer(&info->status_timer); + mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); } diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 7fd3cd5..be73c80 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -88,9 +88,8 @@ static struct sysrq_key_op sysrq_loglevel_op = { #ifdef CONFIG_VT static void sysrq_handle_SAK(int key, struct tty_struct *tty) { - if (tty) - do_SAK(tty); - reset_vc(vc_cons[fg_console].d); + struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; + schedule_work(SAK_work); } static struct sysrq_key_op sysrq_SAK_op = { .handler = sysrq_handle_SAK, diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 07067c3..c346ec5 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -68,6 +68,7 @@ #include <linux/init.h> #include <linux/stat.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/toshiba.h> @@ -298,12 +299,10 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, * Print the information for /proc/toshiba */ #ifdef CONFIG_PROC_FS -static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) +static int proc_toshiba_show(struct seq_file *m, void *v) { - char *temp; int key; - temp = buffer; key = tosh_fn_status(); /* Arguments @@ -314,8 +313,7 @@ static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) 4) BIOS date (in SCI date format) 5) Fn Key status */ - - temp += sprintf(temp, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", + seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", tosh_id, (tosh_sci & 0xff00)>>8, tosh_sci & 0xff, @@ -323,9 +321,21 @@ static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) tosh_bios & 0xff, tosh_date, key); + return 0; +} - return temp-buffer; +static int proc_toshiba_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_toshiba_show, NULL); } + +static const struct file_operations proc_toshiba_fops = { + .owner = THIS_MODULE, + .open = proc_toshiba_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif @@ -508,10 +518,15 @@ static int __init toshiba_init(void) return retval; #ifdef CONFIG_PROC_FS - /* register the proc entry */ - if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) { - misc_deregister(&tosh_device); - return -ENOMEM; + { + struct proc_dir_entry *pde; + + pde = create_proc_entry("toshiba", 0, NULL); + if (!pde) { + misc_deregister(&tosh_device); + return -ENOMEM; + } + pde->proc_fops = &proc_toshiba_fops; } #endif diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 33e1f66..2f572b9 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1107,9 +1107,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend INIT_WORK(&chip->work, timeout_work); - init_timer(&chip->user_read_timer); - chip->user_read_timer.function = user_reader_timeout; - chip->user_read_timer.data = (unsigned long) chip; + setup_timer(&chip->user_read_timer, user_reader_timeout, + (unsigned long)chip); memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index a611972..4eba32b 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c @@ -372,10 +372,8 @@ static int read_log(struct tpm_bios_log *log) } /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ - status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1, - ACPI_LOGICAL_ADDRESSING, - (struct acpi_table_header **) - &buff); + status = acpi_get_table(ACPI_SIG_TCPA, 1, + (struct acpi_table_header **)&buff); if (ACPI_FAILURE(status)) { printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", @@ -409,7 +407,7 @@ static int read_log(struct tpm_bios_log *log) log->bios_event_log_end = log->bios_event_log + len; - acpi_os_map_memory(start, len, (void *) &virt); + virt = acpi_os_map_memory(start, len); memcpy(log->bios_event_log, virt, len); @@ -443,7 +441,7 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode, return err; } -struct file_operations tpm_ascii_bios_measurements_ops = { +const struct file_operations tpm_ascii_bios_measurements_ops = { .open = tpm_ascii_bios_measurements_open, .read = seq_read, .llseek = seq_lseek, @@ -476,7 +474,7 @@ static int tpm_binary_bios_measurements_open(struct inode *inode, return err; } -struct file_operations tpm_binary_bios_measurements_ops = { +const struct file_operations tpm_binary_bios_measurements_ops = { .open = tpm_binary_bios_measurements_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 47a6eac..5289254 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -154,7 +154,9 @@ static int tty_release(struct inode *, struct file *); int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); -static void release_mem(struct tty_struct *tty, int idx); +static void release_tty(struct tty_struct *tty, int idx); +static struct pid *__proc_set_tty(struct task_struct *tsk, + struct tty_struct *tty); /** * alloc_tty_struct - allocate a tty object @@ -1109,17 +1111,17 @@ int tty_check_change(struct tty_struct * tty) { if (current->signal->tty != tty) return 0; - if (tty->pgrp <= 0) { - printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); + if (!tty->pgrp) { + printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); return 0; } - if (process_group(current) == tty->pgrp) + if (task_pgrp(current) == tty->pgrp) return 0; if (is_ignored(SIGTTOU)) return 0; - if (is_orphaned_pgrp(process_group(current))) + if (is_current_pgrp_orphaned()) return -EIO; - (void) kill_pg(process_group(current), SIGTTOU, 1); + (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1); return -ERESTARTSYS; } @@ -1354,8 +1356,8 @@ static void do_tty_hangup(struct work_struct *work) tty_release is called */ read_lock(&tasklist_lock); - if (tty->session > 0) { - do_each_task_pid(tty->session, PIDTYPE_SID, p) { + if (tty->session) { + do_each_pid_task(tty->session, PIDTYPE_SID, p) { spin_lock_irq(&p->sighand->siglock); if (p->signal->tty == tty) p->signal->tty = NULL; @@ -1365,16 +1367,17 @@ static void do_tty_hangup(struct work_struct *work) } __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); - if (tty->pgrp > 0) - p->signal->tty_old_pgrp = tty->pgrp; + put_pid(p->signal->tty_old_pgrp); /* A noop */ + if (tty->pgrp) + p->signal->tty_old_pgrp = get_pid(tty->pgrp); spin_unlock_irq(&p->sighand->siglock); - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + } while_each_pid_task(tty->session, PIDTYPE_SID, p); } read_unlock(&tasklist_lock); tty->flags = 0; - tty->session = 0; - tty->pgrp = -1; + tty->session = NULL; + tty->pgrp = NULL; tty->ctrl_status = 0; /* * If one of the devices matches a console pointer, we @@ -1459,12 +1462,12 @@ int tty_hung_up_p(struct file * filp) EXPORT_SYMBOL(tty_hung_up_p); -static void session_clear_tty(pid_t session) +static void session_clear_tty(struct pid *session) { struct task_struct *p; - do_each_task_pid(session, PIDTYPE_SID, p) { + do_each_pid_task(session, PIDTYPE_SID, p) { proc_clear_tty(p); - } while_each_task_pid(session, PIDTYPE_SID, p); + } while_each_pid_task(session, PIDTYPE_SID, p); } /** @@ -1494,46 +1497,54 @@ static void session_clear_tty(pid_t session) void disassociate_ctty(int on_exit) { struct tty_struct *tty; - int tty_pgrp = -1; - int session; + struct pid *tty_pgrp = NULL; lock_kernel(); mutex_lock(&tty_mutex); tty = get_current_tty(); if (tty) { - tty_pgrp = tty->pgrp; + tty_pgrp = get_pid(tty->pgrp); mutex_unlock(&tty_mutex); /* XXX: here we race, there is nothing protecting tty */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); - } else { - pid_t old_pgrp = current->signal->tty_old_pgrp; + } else if (on_exit) { + struct pid *old_pgrp; + spin_lock_irq(¤t->sighand->siglock); + old_pgrp = current->signal->tty_old_pgrp; + current->signal->tty_old_pgrp = NULL; + spin_unlock_irq(¤t->sighand->siglock); if (old_pgrp) { - kill_pg(old_pgrp, SIGHUP, on_exit); - kill_pg(old_pgrp, SIGCONT, on_exit); + kill_pgrp(old_pgrp, SIGHUP, on_exit); + kill_pgrp(old_pgrp, SIGCONT, on_exit); + put_pid(old_pgrp); } mutex_unlock(&tty_mutex); unlock_kernel(); return; } - if (tty_pgrp > 0) { - kill_pg(tty_pgrp, SIGHUP, on_exit); + if (tty_pgrp) { + kill_pgrp(tty_pgrp, SIGHUP, on_exit); if (!on_exit) - kill_pg(tty_pgrp, SIGCONT, on_exit); + kill_pgrp(tty_pgrp, SIGCONT, on_exit); + put_pid(tty_pgrp); } spin_lock_irq(¤t->sighand->siglock); + tty_pgrp = current->signal->tty_old_pgrp; current->signal->tty_old_pgrp = 0; - session = process_session(current); spin_unlock_irq(¤t->sighand->siglock); + put_pid(tty_pgrp); mutex_lock(&tty_mutex); /* It is possible that do_tty_hangup has free'd this tty */ tty = get_current_tty(); if (tty) { - tty->session = 0; - tty->pgrp = 0; + put_pid(tty->session); + put_pid(tty->pgrp); + tty->session = NULL; + tty->pgrp = NULL; } else { #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "error attempted to write to tty [0x%p]" @@ -1544,7 +1555,7 @@ void disassociate_ctty(int on_exit) /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); - session_clear_tty(session); + session_clear_tty(task_session(current)); read_unlock(&tasklist_lock); unlock_kernel(); } @@ -1612,7 +1623,6 @@ void start_tty(struct tty_struct *tty) /* If we have a running line discipline it may need kicking */ tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); } EXPORT_SYMBOL(start_tty); @@ -2003,7 +2013,7 @@ static int init_dev(struct tty_driver *driver, int idx, /* * All structures have been allocated, so now we install them. - * Failures after this point use release_mem to clean up, so + * Failures after this point use release_tty to clean up, so * there's no need to null out the local pointers. */ if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { @@ -2024,8 +2034,8 @@ static int init_dev(struct tty_driver *driver, int idx, /* * Structures all installed ... call the ldisc open routines. - * If we fail here just call release_mem to clean up. No need - * to decrement the use counts, as release_mem doesn't care. + * If we fail here just call release_tty to clean up. No need + * to decrement the use counts, as release_tty doesn't care. */ if (tty->ldisc.open) { @@ -2095,17 +2105,17 @@ fail_no_mem: retval = -ENOMEM; goto end_init; - /* call the tty release_mem routine to clean out this slot */ + /* call the tty release_tty routine to clean out this slot */ release_mem_out: if (printk_ratelimit()) printk(KERN_INFO "init_dev: ldisc open failed, " "clearing slot %d\n", idx); - release_mem(tty, idx); + release_tty(tty, idx); goto end_init; } /** - * release_mem - release tty structure memory + * release_one_tty - release tty structure memory * * Releases memory associated with a tty structure, and clears out the * driver table slots. This function is called when a device is no longer @@ -2117,37 +2127,14 @@ release_mem_out: * of ttys that the driver keeps. * FIXME: should we require tty_mutex is held here ?? */ - -static void release_mem(struct tty_struct *tty, int idx) +static void release_one_tty(struct tty_struct *tty, int idx) { - struct tty_struct *o_tty; - struct ktermios *tp; int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; - - if ((o_tty = tty->link) != NULL) { - if (!devpts) - o_tty->driver->ttys[idx] = NULL; - if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { - tp = o_tty->termios; - if (!devpts) - o_tty->driver->termios[idx] = NULL; - kfree(tp); - - tp = o_tty->termios_locked; - if (!devpts) - o_tty->driver->termios_locked[idx] = NULL; - kfree(tp); - } - o_tty->magic = 0; - o_tty->driver->refcount--; - file_list_lock(); - list_del_init(&o_tty->tty_files); - file_list_unlock(); - free_tty_struct(o_tty); - } + struct ktermios *tp; if (!devpts) tty->driver->ttys[idx] = NULL; + if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { tp = tty->termios; if (!devpts) @@ -2160,15 +2147,39 @@ static void release_mem(struct tty_struct *tty, int idx) kfree(tp); } + tty->magic = 0; tty->driver->refcount--; + file_list_lock(); list_del_init(&tty->tty_files); file_list_unlock(); - module_put(tty->driver->owner); + free_tty_struct(tty); } +/** + * release_tty - release tty structure memory + * + * Release both @tty and a possible linked partner (think pty pair), + * and decrement the refcount of the backing module. + * + * Locking: + * tty_mutex - sometimes only + * takes the file list lock internally when working on the list + * of ttys that the driver keeps. + * FIXME: should we require tty_mutex is held here ?? + */ +static void release_tty(struct tty_struct *tty, int idx) +{ + struct tty_driver *driver = tty->driver; + + if (tty->link) + release_one_tty(tty->link, idx); + release_one_tty(tty, idx); + module_put(driver->owner); +} + /* * Even releasing the tty structures is a tricky business.. We have * to be very careful that the structures are all released at the @@ -2436,10 +2447,10 @@ static void release_dev(struct file * filp) tty_set_termios_ldisc(o_tty,N_TTY); } /* - * The release_mem function takes care of the details of clearing + * The release_tty function takes care of the details of clearing * the slots and preserving the termios structure. */ - release_mem(tty, idx); + release_tty(tty, idx); #ifdef CONFIG_UNIX98_PTYS /* Make this pty number available for reallocation */ @@ -2481,6 +2492,7 @@ static int tty_open(struct inode * inode, struct file * filp) int index; dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; + struct pid *old_pgrp; nonseekable_open(inode, filp); @@ -2574,15 +2586,17 @@ got_driver: goto retry_open; } + old_pgrp = NULL; mutex_lock(&tty_mutex); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && !current->signal->tty && - tty->session == 0) - __proc_set_tty(current, tty); + tty->session == NULL) + old_pgrp = __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); mutex_unlock(&tty_mutex); + put_pid(old_pgrp); return 0; } @@ -2721,9 +2735,18 @@ static int tty_fasync(int fd, struct file * filp, int on) return retval; if (on) { + enum pid_type type; + struct pid *pid; if (!waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = 1; - retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0); + if (tty->pgrp) { + pid = tty->pgrp; + type = PIDTYPE_PGID; + } else { + pid = task_pid(current); + type = PIDTYPE_PID; + } + retval = __f_setown(filp, pid, type, 0); if (retval) return retval; } else { @@ -2825,10 +2848,10 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, } } #endif - if (tty->pgrp > 0) - kill_pg(tty->pgrp, SIGWINCH, 1); - if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0)) - kill_pg(real_tty->pgrp, SIGWINCH, 1); + if (tty->pgrp) + kill_pgrp(tty->pgrp, SIGWINCH, 1); + if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp) + kill_pgrp(real_tty->pgrp, SIGWINCH, 1); tty->winsize = tmp_ws; real_tty->winsize = tmp_ws; done: @@ -2913,8 +2936,7 @@ static int fionbio(struct file *file, int __user *p) static int tiocsctty(struct tty_struct *tty, int arg) { int ret = 0; - if (current->signal->leader && - (process_session(current) == tty->session)) + if (current->signal->leader && (task_session(current) == tty->session)) return ret; mutex_lock(&tty_mutex); @@ -2927,7 +2949,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) goto unlock; } - if (tty->session > 0) { + if (tty->session) { /* * This tty is already the controlling * tty for another session group! @@ -2970,7 +2992,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t */ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; - return put_user(real_tty->pgrp, p); + return put_user(pid_nr(real_tty->pgrp), p); } /** @@ -2987,7 +3009,8 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { - pid_t pgrp; + struct pid *pgrp; + pid_t pgrp_nr; int retval = tty_check_change(real_tty); if (retval == -EIO) @@ -2996,16 +3019,26 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return retval; if (!current->signal->tty || (current->signal->tty != real_tty) || - (real_tty->session != process_session(current))) + (real_tty->session != task_session(current))) return -ENOTTY; - if (get_user(pgrp, p)) + if (get_user(pgrp_nr, p)) return -EFAULT; - if (pgrp < 0) + if (pgrp_nr < 0) return -EINVAL; - if (session_of_pgrp(pgrp) != process_session(current)) - return -EPERM; - real_tty->pgrp = pgrp; - return 0; + rcu_read_lock(); + pgrp = find_pid(pgrp_nr); + retval = -ESRCH; + if (!pgrp) + goto out_unlock; + retval = -EPERM; + if (session_of_pgrp(pgrp) != task_session(current)) + goto out_unlock; + retval = 0; + put_pid(real_tty->pgrp); + real_tty->pgrp = get_pid(pgrp); +out_unlock: + rcu_read_unlock(); + return retval; } /** @@ -3028,9 +3061,9 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ */ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; - if (real_tty->session <= 0) + if (!real_tty->session) return -ENOTTY; - return put_user(real_tty->session, p); + return put_user(pid_nr(real_tty->session), p); } /** @@ -3324,15 +3357,13 @@ int tty_ioctl(struct inode * inode, struct file * file, * Nasty bug: do_SAK is being called in interrupt context. This can * deadlock. We punt it up to process context. AKPM - 16Mar2001 */ -static void __do_SAK(struct work_struct *work) +void __do_SAK(struct tty_struct *tty) { - struct tty_struct *tty = - container_of(work, struct tty_struct, SAK_work); #ifdef TTY_SOFT_SAK tty_hangup(tty); #else struct task_struct *g, *p; - int session; + struct pid *session; int i; struct file *filp; struct fdtable *fdt; @@ -3348,12 +3379,12 @@ static void __do_SAK(struct work_struct *work) read_lock(&tasklist_lock); /* Kill the entire session */ - do_each_task_pid(session, PIDTYPE_SID, p) { + do_each_pid_task(session, PIDTYPE_SID, p) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): process_session(p)==tty->session\n", p->pid, p->comm); send_sig(SIGKILL, p, 1); - } while_each_task_pid(session, PIDTYPE_SID, p); + } while_each_pid_task(session, PIDTYPE_SID, p); /* Now kill any processes that happen to have the * tty open. */ @@ -3394,6 +3425,13 @@ static void __do_SAK(struct work_struct *work) #endif } +static void do_SAK_work(struct work_struct *work) +{ + struct tty_struct *tty = + container_of(work, struct tty_struct, SAK_work); + __do_SAK(tty); +} + /* * The tq handling here is a little racy - tty->SAK_work may already be queued. * Fortunately we don't need to worry, because if ->SAK_work is already queued, @@ -3404,7 +3442,6 @@ void do_SAK(struct tty_struct *tty) { if (!tty) return; - PREPARE_WORK(&tty->SAK_work, __do_SAK); schedule_work(&tty->SAK_work); } @@ -3515,7 +3552,8 @@ static void initialize_tty_struct(struct tty_struct *tty) memset(tty, 0, sizeof(struct tty_struct)); tty->magic = TTY_MAGIC; tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); - tty->pgrp = -1; + tty->session = NULL; + tty->pgrp = NULL; tty->overrun_time = jiffies; tty->buf.head = tty->buf.tail = NULL; tty_buffer_init(tty); @@ -3529,7 +3567,7 @@ static void initialize_tty_struct(struct tty_struct *tty) mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->read_lock); INIT_LIST_HEAD(&tty->tty_files); - INIT_WORK(&tty->SAK_work, NULL); + INIT_WORK(&tty->SAK_work, do_SAK_work); } /* @@ -3786,21 +3824,28 @@ void proc_clear_tty(struct task_struct *p) } EXPORT_SYMBOL(proc_clear_tty); -void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) { + struct pid *old_pgrp; if (tty) { - tty->session = process_session(tsk); - tty->pgrp = process_group(tsk); + tty->session = get_pid(task_session(tsk)); + tty->pgrp = get_pid(task_pgrp(tsk)); } + old_pgrp = tsk->signal->tty_old_pgrp; tsk->signal->tty = tty; - tsk->signal->tty_old_pgrp = 0; + tsk->signal->tty_old_pgrp = NULL; + return old_pgrp; } void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) { + struct pid *old_pgrp; + spin_lock_irq(&tsk->sighand->siglock); - __proc_set_tty(tsk, tty); + old_pgrp = __proc_set_tty(tsk, tty); spin_unlock_irq(&tsk->sighand->siglock); + + put_pid(old_pgrp); } struct tty_struct *get_current_tty(void) diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index dee47f4..fd471cb 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -225,7 +225,7 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); /** * tty_termios_encode_baud_rate - * @termios: termios structure + * @termios: ktermios structure holding user requested state * @ispeed: input speed * @ospeed: output speed * @@ -233,7 +233,10 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); * used as a library helper for drivers os that they can report back * the actual speed selected when it differs from the speed requested * - * For now input and output speed must agree. + * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour + * we need to carefully set the bits when the user does not get the + * desired speed. We allow small margins and preserve as much of possible + * of the input intent to keep compatiblity. * * Locking: Caller should hold termios lock. This is already held * when calling this function from the driver termios handler. @@ -242,32 +245,44 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) { int i = 0; - int ifound = 0, ofound = 0; + int ifound = -1, ofound = -1; + int iclose = ibaud/50, oclose = obaud/50; + int ibinput = 0; termios->c_ispeed = ibaud; termios->c_ospeed = obaud; + /* If the user asked for a precise weird speed give a precise weird + answer. If they asked for a Bfoo speed they many have problems + digesting non-exact replies so fuzz a bit */ + + if ((termios->c_cflag & CBAUD) == BOTHER) + oclose = 0; + if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) + iclose = 0; + if ((termios->c_cflag >> IBSHIFT) & CBAUD) + ibinput = 1; /* An input speed was specified */ + termios->c_cflag &= ~CBAUD; - /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/ - if (termios->c_ispeed == termios->c_ospeed) - ifound = 1; do { - if (obaud == baud_table[i]) { + if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) { termios->c_cflag |= baud_bits[i]; - ofound = 1; - /* So that if ibaud == obaud we don't set it */ - continue; + ofound = i; } - if (ibaud == baud_table[i]) { - termios->c_cflag |= (baud_bits[i] << IBSHIFT); - ifound = 1; + if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) { + /* For the case input == output don't set IBAUD bits if the user didn't do so */ + if (ofound != i || ibinput) + termios->c_cflag |= (baud_bits[i] << IBSHIFT); + ifound = i; } } while(++i < n_baud_table); - if (!ofound) + if (ofound == -1) termios->c_cflag |= BOTHER; - if (!ifound) + /* Set exact input bits only if the input and output differ or the + user already did */ + if (ifound == -1 && (ibaud != obaud || ibinput)) termios->c_cflag |= (BOTHER << IBSHIFT); } diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 9438512..13faf8d 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -872,7 +872,7 @@ free_op: return ret; } -struct file_operations viotap_fops = { +const struct file_operations viotap_fops = { owner: THIS_MODULE, read: viotap_read, write: viotap_write, diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 06c32a3..c3f8e38 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -136,9 +136,6 @@ const struct consw *conswitchp; #define DEFAULT_BELL_PITCH 750 #define DEFAULT_BELL_DURATION (HZ/8) -extern void vcs_make_sysfs(struct tty_struct *tty); -extern void vcs_remove_sysfs(struct tty_struct *tty); - struct vc vc_cons [MAX_NR_CONSOLES]; #ifndef VT_SINGLE_DRIVER @@ -213,7 +210,7 @@ static int scrollback_delta; */ int (*console_blank_hook)(int); -static struct timer_list console_timer; +static DEFINE_TIMER(console_timer, blank_screen_t, 0, 0); static int blank_state; static int blank_timer_expired; enum { @@ -869,8 +866,8 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) ws.ws_col = vc->vc_cols; ws.ws_ypixel = vc->vc_scan_lines; if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && - vc->vc_tty->pgrp > 0) - kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1); + vc->vc_tty->pgrp) + kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1); *cws = ws; } @@ -2628,8 +2625,6 @@ static int __init con_init(void) for (i = 0; i < MAX_NR_CONSOLES; i++) con_driver_map[i] = conswitchp; - init_timer(&console_timer); - console_timer.function = blank_screen_t; if (blankinterval) { blank_state = blank_normal_wait; mod_timer(&console_timer, jiffies + blankinterval); @@ -2640,6 +2635,7 @@ static int __init con_init(void) */ for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data)); + INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); visual_init(vc, currcons, 1); vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size); vc->vc_kmalloced = 0; diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index dc8368e..3a5d301 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -672,7 +672,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, vc->vt_mode = tmp; /* the frsig is ignored, so we set it to 0 */ vc->vt_mode.frsig = 0; - put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current)))); + put_pid(vc->vt_pid); + vc->vt_pid = get_pid(task_pid(current)); /* no switch is required -- saw@shade.msu.ru */ vc->vt_newvt = -1; release_console_sem(); @@ -1063,12 +1064,35 @@ void reset_vc(struct vc_data *vc) vc->vt_mode.relsig = 0; vc->vt_mode.acqsig = 0; vc->vt_mode.frsig = 0; - put_pid(xchg(&vc->vt_pid, NULL)); + put_pid(vc->vt_pid); + vc->vt_pid = NULL; vc->vt_newvt = -1; if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ reset_palette(vc); } +void vc_SAK(struct work_struct *work) +{ + struct vc *vc_con = + container_of(work, struct vc, SAK_work); + struct vc_data *vc; + struct tty_struct *tty; + + acquire_console_sem(); + vc = vc_con->d; + if (vc) { + tty = vc->vc_tty; + /* + * SAK should also work in all raw modes and reset + * them properly. + */ + if (tty) + __do_SAK(tty); + reset_vc(vc); + } + release_console_sem(); +} + /* * Performs the back end of a vt switch */ diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index c195078..67aed9f 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c @@ -410,10 +410,8 @@ module_init(alim7101_wdt_init); module_exit(alim7101_wdt_unload); static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, + { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { } }; diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 4889022..0e23f29 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c @@ -35,7 +35,7 @@ #ifdef CONFIG_FSL_BOOKE #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ #else -#define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */ +#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ #endif /* for timing information */ u32 booke_wdt_enabled = 0; @@ -48,12 +48,22 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT; #endif /* + * booke_wdt_ping: + */ +static __inline__ void booke_wdt_ping(void) +{ + mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); +} + +/* * booke_wdt_enable: */ static __inline__ void booke_wdt_enable(void) { u32 val; + /* clear status before enabling watchdog */ + booke_wdt_ping(); val = mfspr(SPRN_TCR); val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); @@ -61,14 +71,6 @@ static __inline__ void booke_wdt_enable(void) } /* - * booke_wdt_ping: - */ -static __inline__ void booke_wdt_ping(void) -{ - mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); -} - -/* * booke_wdt_write: */ static ssize_t booke_wdt_write (struct file *file, const char __user *buf, diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 8b13dfa..3c9684c 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -539,7 +539,7 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, * Kernel Interfaces */ -static struct file_operations iTCO_wdt_fops = { +static const struct file_operations iTCO_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = iTCO_wdt_write, diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 4a328ba..81fb3de 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -324,7 +324,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(0, p); case WDIOC_KEEPALIVE: - zf_ping(0); + zf_ping(NULL); break; default: diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index 6c6f973..84074a6 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c @@ -230,7 +230,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file, } } -static struct file_operations omap_wdt_fops = { +static const struct file_operations omap_wdt_fops = { .owner = THIS_MODULE, .write = omap_wdt_write, .ioctl = omap_wdt_ioctl, diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index 4faea2f..3d3deae 100644 --- a/drivers/char/watchdog/pc87413_wdt.c +++ b/drivers/char/watchdog/pc87413_wdt.c @@ -526,7 +526,7 @@ static int pc87413_notify_sys(struct notifier_block *this, /* -- Module's structures ---------------------------------------*/ -static struct file_operations pc87413_fops = { +static const struct file_operations pc87413_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = pc87413_write, diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c index 0e3d589..5991add 100644 --- a/drivers/char/watchdog/pnx4008_wdt.c +++ b/drivers/char/watchdog/pnx4008_wdt.c @@ -238,7 +238,7 @@ static int pnx4008_wdt_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations pnx4008_wdt_fops = { +static const struct file_operations pnx4008_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = pnx4008_wdt_write, diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 7576a13..b467883 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c @@ -95,7 +95,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); /* Kernel interfaces */ -static struct file_operations fops = { +static const struct file_operations fops = { .owner = THIS_MODULE, .open = wdt_gpi_open, .release = wdt_gpi_release, diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c index aa977f1..d3cb0a7 100644 --- a/drivers/char/watchdog/smsc37b787_wdt.c +++ b/drivers/char/watchdog/smsc37b787_wdt.c @@ -510,7 +510,7 @@ static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long cod /* -- Module's structures ---------------------------------------*/ -static struct file_operations wb_smsc_wdt_fops = +static const struct file_operations wb_smsc_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index f9f6f54..d9e821d 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -323,7 +323,7 @@ wdt_notify_sys(struct notifier_block *this, unsigned long code, * Kernel Interfaces */ -static struct file_operations wdt_fops = { +static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wdt_write, |